### To Do 

# Actual statistics for relationships between temperature and CTmax, size, and fecundity
# Pull residuals from CTmax ~ temperature model, and examine the change over time in lab and the relationship with fecundity

Copepod Collection

Copepods were collected at approximately weekly intervals from Lake Champlain (Burlington Fishing Pier). Plankton was collected from the top 3 meters using a 250 um mesh net.

# Lake Champlain near Burlington, VT
siteNumber = "04294500"
ChamplainInfo = readNWISsite(siteNumber)
parameterCd = "00010"
startDate = "2023-01-01"
endDate = ""
#statCd = c("00001", "00002","00003", "00011") # 1 - max, 2 - min, 3 = mean

# Constructs the URL for the data wanted then downloads the data
url = constructNWISURL(siteNumbers = siteNumber, parameterCd = parameterCd, 
                       startDate = startDate, endDate = endDate, service = "uv")

temp_data = importWaterML1(url, asDateTime = T) %>% 
  mutate("date" = as.Date(dateTime)) %>% 
  select(date, "temp" = X_00010_00000)

Collections began in late May 2023. Several gaps are present, but collections have continued at roughly weekly intervals since then. Copepods from 22 collections were used to make a total of 544 thermal limit measurements. Over this time period, collection temperatures ranged from 10.5 to 26.5°C.

There is substantial variation in thermal limits across the species collected. There is also some degree of variation within the species, with thermal limits increasing slightly during the summer.

## Daily values for the period examined by dataset
collection_conditions = temp_data %>%
  ungroup() %>% 
  group_by(date) %>% 
  summarise(mean_temp = mean(temp),
            med_temp = median(temp),
            var_temp = var(temp), 
            min_temp = min(temp), 
            max_temp = max(temp)) %>% 
  mutate("range_temp" = max_temp - min_temp,
         date = as.Date(date)) %>% 
  ungroup() %>%  
  filter(date >= (min(as.Date(full_data$collection_date)) - 7))

## Mean female thermal limits for each species, grouped by collection
species_summaries = full_data %>%  
  #filter(sex == "female") %>% 
  group_by(sp_name, collection_date, collection_temp) %>%  
  summarise("mean_ctmax" = mean(ctmax),
            "sample_size" = n(),
            "ctmax_st_err" = (sd(ctmax) / sqrt(sample_size)),
            "ctmax_var" = var(ctmax), 
            "mean_size" = mean(size),
            "size_st_err" = (sd(size) / sqrt(sample_size)),
            "size_var" = var(size)) %>%  
  ungroup() %>% 
  complete(sp_name, collection_date) %>% 
  arrange(desc(sample_size))

adult_summaries = full_data %>%  
  filter(sex == "female") %>% 
  group_by(sp_name, collection_date, collection_temp) %>%  
  summarise("mean_ctmax" = mean(ctmax),
            "sample_size" = n(),
            "ctmax_st_err" = (sd(ctmax) / sqrt(sample_size)),
            "ctmax_var" = var(ctmax), 
            "mean_size" = mean(size),
            "size_st_err" = (sd(size) / sqrt(sample_size)),
            "size_var" = var(size)) %>%  
  ungroup() %>% 
  complete(sp_name, collection_date) %>% 
  arrange(desc(sample_size))


ggplot() + 
  geom_vline(data = unique(select(full_data, collection_date)), 
             aes(xintercept = as.Date(collection_date)),
             colour = "grey90",
             linewidth = 1) + 
  geom_line(data = collection_conditions, 
            aes(x = as.Date(date), y = mean_temp),
            colour = "black", 
            linewidth = 2) + 
  # geom_errorbar(data = species_summaries,
  #               aes(x = as.Date(collection_date),
  #                   ymin = mean_ctmax - ctmax_st_err, ymax = mean_ctmax + ctmax_st_err,
  #                   colour = sp_name),
  #               position = position_dodge(width = 1),
  #               width = 5, linewidth = 1) +
  geom_point(data = adult_summaries, 
             aes(x = as.Date(collection_date), y = mean_ctmax, colour = sp_name, size = sample_size)) + 
  scale_colour_manual(values = species_cols) + 
  labs(x = "Date", 
       y = "Temperature (°C)", 
       colour = "Species",
       size = "Sample Size") + 
  theme_matt() + 
  theme(legend.position = "right")

Size also varied both between and within species.

ggplot() + 
  geom_vline(data = unique(select(full_data, collection_date)), 
             aes(xintercept = as.Date(collection_date)),
             colour = "grey90",
             linewidth = 1) + 
  geom_line(data = collection_conditions, 
            aes(x = as.Date(date), y = mean_temp),
            colour = "black", 
            linewidth = 2) + 
  # geom_errorbar(data = species_summaries,
  #               aes(x = as.Date(collection_date), 
  #                   ymin = mean_ctmax - ctmax_st_err, ymax = mean_ctmax + ctmax_st_err,
  #                   colour = sp_name),
  #               position = position_dodge(width = 1),
  #               width = 5, linewidth = 1) + 
  geom_point(data = adult_summaries, 
             aes(x = as.Date(collection_date), y = mean_size * 40, colour = sp_name, size = sample_size),
             position = position_dodge(width = 1)) + 
  scale_colour_manual(values = species_cols) + 
  scale_y_continuous(
    name = "Temperature", # Features of the first axis
    sec.axis = sec_axis(~./40, name="Prosome Length (mm)"), # Add a second axis and specify its features
    breaks = c(0,5,10,15,20,25,30)
  ) + 
  labs(x = "Date", 
       y = "Temperature (°C)", 
       colour = "Species") + 
  theme_matt() + 
  theme(legend.position = "right")

For the three species with the most data (Skistodiaptomus, L. minutus, Epischura), shown below is CTmax and body size, plotted against the day of the year for each sex/stage separately.

ctmax_feature = full_data %>%  
  mutate(doy = yday(collection_date)) %>% 
  filter(sp_name %in% c("Skistodiaptomus oregonensis", "Leptodiaptomus minutus", "Epischura lacustris")) %>% 
  ggplot(aes(x = doy, y = ctmax, colour = sp_name)) + 
  facet_grid(sp_name~sex) + 
  geom_point() + 
  scale_colour_manual(values = species_cols) + 
  labs(x = "Day of the Year", 
       y = "CTmax (°C)") + 
  guides(color = FALSE) + 
  theme_matt_facets() +
  theme(axis.text.x = element_text(angle = 300, hjust = 0, vjust = 0.5))

size_feature = full_data %>%  
  mutate(doy = yday(collection_date)) %>% 
  filter(sp_name %in% c("Skistodiaptomus oregonensis", "Leptodiaptomus minutus", "Epischura lacustris")) %>% 
  ggplot(aes(x = doy, y = size, colour = sp_name)) + 
  facet_grid(sp_name~sex) + 
  geom_point() + 
  scale_colour_manual(values = species_cols) + 
  labs(x = "Day of the Year", 
       y = "Size (mm)") + 
  guides(color = FALSE) + 
  theme_matt_facets() +
  theme(axis.text.x = element_text(angle = 300, hjust = 0, vjust = 0.5))

ggarrange(ctmax_feature, size_feature, common.legend = T, legend = "bottom")

Temperature Variability

Lake Champlain is highly seasonal, with both average temperatures and temperature variability changing throughout the year. These patterns in the experienced thermal environment may drive the observed variation in copepod thermal limits. However, the time period affecting copepod thermal limits is unknown. Depending the on the duration of time considered, there are large changes in the experienced environment, in particular regarding the temperature range and variance. Consider for example three time periods: the day of collection, one week prior to collection, and four weeks prior to collection. While the overall pattern is similar, we can see that, unsurprisingly, considering longer periods of time results in larger ranges and slightly changes the pattern of variance experienced.

## Daily values
daily_temp_data = temp_data %>%
  ungroup() %>% 
  group_by(date) %>% 
  summarise(mean_temp = mean(temp),
            med_temp = median(temp),
            var_temp = var(temp), 
            min_temp = min(temp), 
            max_temp = max(temp)) %>% 
  mutate("range_temp" = max_temp - min_temp)

day_prior_temp_data = temp_data %>% 
  ungroup() %>% 
  group_by(date) %>% 
  summarise(mean_temp = mean(temp),
            med_temp = median(temp),
            var_temp = var(temp), 
            min_temp = min(temp), 
            max_temp = max(temp)) %>% 
  mutate(date = date + 1) %>% 
  rename_with(.fn = ~ paste0("prior_day_", .x), .cols = c(-date))

daily_plot = daily_temp_data %>% 
  pivot_longer(cols = c(-date),
               names_to = "parameter", 
               values_to = "temp") %>% 
  ggplot(aes(x = date, y = temp, colour = parameter)) + 
  geom_line(linewidth = 1) + 
  scale_colour_manual(values = c(
    "mean_temp" = "olivedrab3",
    "med_temp" = "seagreen3",
    "max_temp" = "tomato",  
    "min_temp" = "dodgerblue",
    "range_temp" = "goldenrod3",
    "var_temp" = "darkgoldenrod1"
  )) + 
  scale_x_continuous(breaks = as.Date(c("2023-01-01", "2023-04-01", "2023-07-01"))) + 
  ggtitle("Daily Values") + 
  labs(y = "Temperature (°C)",
       x = "") + 
  theme_bw(base_size = 20) + 
  theme(panel.grid = element_blank(),
        axis.text.x = element_text(angle = 270, hjust = 0, vjust = 0.5))
## Defining the function to get predictor values for periods of different lengths
get_predictors = function(daily_values, raw_temp, n_days){
  prefix = str_replace_all(xfun::numbers_to_words(n_days), pattern = " ", replacement = "-")
  
  mean_values = daily_values %>% 
    ungroup() %>% 
    mutate(mean_max = slide_vec(.x = max_temp, .f = mean, .before = n_days, .complete = T),
           mean_min = slide_vec(.x = min_temp, .f = mean, .before = n_days, .complete = T),
           mean_range = slide_vec(.x = range_temp, .f = mean, .before = n_days, .complete = T)) %>% 
    select(date, mean_max, mean_min, mean_range) %>% 
    rename_with( ~ paste(prefix, "day", .x, sep = "_"), .cols = c(-date))
  
  period_values = raw_temp %>% 
    mutate(mean = slide_index_mean(temp, i = date, before = days(n_days), 
                                   na_rm = T),
           max = slide_index_max(temp, i = date, before = days(n_days), 
                                 na_rm = T),
           min = slide_index_min(temp, i = date, before = days(n_days),
                                 na_rm = T),
           med = slide_index_dbl(temp, .i = date, .before = days(n_days), 
                                 na_rm = T, .f = median),
           var = slide_index_dbl(temp, .i = date, .before = days(n_days), 
                                 .f = var),
           range = max - min) %>%  
    select(-temp) %>%  
    distinct() %>% 
    rename_with( ~ paste(prefix, "day", .x, sep = "_"), .cols = c(-date))%>% 
    inner_join(mean_values, by = c("date")) %>%  
    drop_na()
  
  return(period_values)
}
# ## Getting predictor variables for different periods
# 
# ### Short (three days)
# three_day_temps = get_predictors(daily_values = daily_temp_data, 
#                                  raw_temp = temp_data, 
#                                  n_days = 3)
# 
# ### ONE WEEK
week_temps = get_predictors(daily_values = daily_temp_data,
                            raw_temp = temp_data,
                            n_days = 7)

week_plot = week_temps %>%
  pivot_longer(cols = c(-date),
               names_to = "parameter",
               values_to = "temp") %>%
  filter(parameter %in% c("seven_day_mean",
                          "seven_day_med",
                          "seven_day_max",
                          "seven_day_min",
                          "seven_day_var",
                          "seven_day_range")) %>%
  mutate(parameter = paste(word(parameter, start = 3, sep = fixed("_")), "_temp", sep = "")) %>%
  ggplot(aes(x = date, y = temp, colour = parameter)) +
  geom_line(linewidth = 1) +
  scale_colour_manual(values = c(
    "mean_temp" = "olivedrab3",
    "med_temp" = "seagreen3",
    "max_temp" = "tomato",
    "min_temp" = "dodgerblue",
    "range_temp" = "goldenrod3",
    "var_temp" = "darkgoldenrod1"
  )) +
  scale_x_continuous(breaks = as.Date(c("2023-01-01", "2023-04-01", "2023-07-01"))) +
  ggtitle("One Week") +
  labs(y = "Temperature (°C)",
       x = "") +
  theme_bw(base_size = 20) +
  theme(panel.grid = element_blank(),
        axis.text.x = element_text(angle = 270, hjust = 0, vjust = 0.5))
# 
# 
# ### TWO WEEKS
# two_week_temps = get_predictors(daily_values = daily_temp_data, 
#                                 raw_temp = temp_data, 
#                                 n_days = 14)
# 
# two_week_plot = two_week_temps %>% 
#   pivot_longer(cols = c(-date),
#                names_to = "parameter", 
#                values_to = "temp") %>% 
#   filter(parameter %in% c("fourteen_day_mean",
#                           "fourteen_day_med",
#                           "fourteen_day_max", 
#                           "fourteen_day_min", 
#                           "fourteen_day_var",
#                           "fourteen_day_range")) %>% 
#   mutate(parameter = paste(word(parameter, start = 3, sep = fixed("_")), "_temp", sep = "")) %>% 
#   ggplot(aes(x = date, y = temp, colour = parameter)) + 
#   geom_line(linewidth = 1) + 
#   scale_colour_manual(values = c(
#     "mean_temp" = "olivedrab3",
#     "med_temp" = "seagreen3",
#     "max_temp" = "tomato",  
#     "min_temp" = "dodgerblue",
#     "range_temp" = "goldenrod3",
#     "var_temp" = "darkgoldenrod1"
#   )) + 
#   scale_x_continuous(breaks = as.Date(c("2023-01-01", "2023-04-01", "2023-07-01"))) + 
#   ggtitle("Two Weeks") + 
#   labs(y = "Temperature (°C)",
#        x = "") + 
#   theme_bw(base_size = 20) + 
#   theme(panel.grid = element_blank(),
#         axis.text.x = element_text(angle = 270, hjust = 0, vjust = 0.5))
# 
# 
# ### FOUR WEEKS
four_week_temps = get_predictors(daily_values = daily_temp_data,
                                 raw_temp = temp_data,
                                 n_days = 28)

four_week_plot = four_week_temps %>%
  pivot_longer(cols = c(-date),
               names_to = "parameter",
               values_to = "temp") %>%
  filter(parameter %in% c("twenty-eight_day_mean",
                          "twenty-eight_day_med",
                          "twenty-eight_day_max",
                          "twenty-eight_day_min",
                          "twenty-eight_day_var",
                          "twenty-eight_day_range")) %>%
  mutate(parameter = paste(word(parameter, start = 3, sep = fixed("_")), "_temp", sep = "")) %>%
  ggplot(aes(x = date, y = temp, colour = parameter)) +
  geom_line(linewidth = 1) +
  scale_colour_manual(values = c(
    "mean_temp" = "olivedrab3",
    "med_temp" = "seagreen3",
    "max_temp" = "tomato",
    "min_temp" = "dodgerblue",
    "range_temp" = "goldenrod3",
    "var_temp" = "darkgoldenrod1"
  )) +
  scale_x_continuous(breaks = as.Date(c("2023-01-01", "2023-04-01", "2023-07-01"))) +
  ggtitle("Four Weeks") +
  labs(y = "Temperature (°C)",
       x = "") +
  theme_bw(base_size = 20) +
  theme(panel.grid = element_blank(),
        axis.text.x = element_text(angle = 270, hjust = 0, vjust = 0.5))
# 
# 
# ### EIGHT WEEKS
# eight_week_temps = get_predictors(daily_values = daily_temp_data, 
#                                   raw_temp = temp_data, 
#                                   n_days = 56)
# 
# eight_week_plot = eight_week_temps %>% 
#   pivot_longer(cols = c(-date),
#                names_to = "parameter", 
#                values_to = "temp") %>% 
#   filter(parameter %in% c("fifty-six_day_mean",
#                           "fifty-six_day_med",
#                           "fifty-six_day_max", 
#                           "fifty-six_day_min", 
#                           "fifty-six_day_var",
#                           "fifty-six_day_range")) %>% 
#   mutate(parameter = paste(word(parameter, start = 3, sep = fixed("_")), "_temp", sep = "")) %>% 
#   ggplot(aes(x = date, y = temp, colour = parameter)) + 
#   geom_line(linewidth = 1) + 
#   scale_colour_manual(values = c(
#     "mean_temp" = "olivedrab3",
#     "med_temp" = "seagreen3",
#     "max_temp" = "tomato",  
#     "min_temp" = "dodgerblue",
#     "range_temp" = "goldenrod3",
#     "var_temp" = "darkgoldenrod1"
#   )) + 
#   scale_x_continuous(breaks = as.Date(c("2023-01-01", "2023-04-01", "2023-07-01"))) + 
#   ggtitle("Eight Weeks") + 
#   labs(y = "Temperature (°C)",
#        x = "") + 
#   theme_bw(base_size = 20) + 
#   theme(panel.grid = element_blank(),
#         axis.text.x = element_text(angle = 270, hjust = 0, vjust = 0.5))
# 
ggarrange(daily_plot, week_plot, four_week_plot, 
          common.legend = T, nrow = 1, legend = "bottom")

The different time periods examined by this climate data highlights that the relationship between minimum and maximum temperatures changes based on the window examined. For example, minimum and maximum temperatures experienced over weekly intervals are closely linked, whereas there is a distinct seasonal cycle in the relationship between minimum and maximum temperatures experienced over periods of four weeks.

one_week_doy_data = week_temps %>% 
  mutate(doy = yday(date))

one_week_temp_circle = ggplot(one_week_doy_data, aes(x = seven_day_mean_max, y = seven_day_mean_min, colour = doy)) + 
  geom_point() + 
  scale_colour_gradient2(
    high = "dodgerblue4",
    mid = "coral2",
    low = "dodgerblue4",
      midpoint = 182.5) + 
  labs(x = "Max. Temp. (°C)",
       y = "Min. Temp. (°C)") + 
  labs(x = "Max. Temp. (°C)",
       y = "Min. Temp. (°C)") + 
  ggtitle("One Week") + 
  theme_matt()

four_week_doy_data = four_week_temps %>% 
  mutate(doy = yday(date))

four_week_temp_circle = ggplot(four_week_doy_data, aes(x = `twenty-eight_day_max`, y = `twenty-eight_day_min`, colour = doy)) + 
  geom_point() + 
  scale_colour_gradient2(
    high = "dodgerblue4",
    mid = "coral2",
    low = "dodgerblue4",
      midpoint = 182.5) + 
  labs(x = "Max. Temp. (°C)",
       y = "Min. Temp. (°C)") + 
  ggtitle("Four Week") + 
  theme_matt()

ggarrange(one_week_temp_circle, four_week_temp_circle,
          common.legend = T, legend = "bottom")

The thermal environment over any period of time may drive patterns in thermal acclimation. To explore the potential effects of different acclimation windows, we examined the correlation between thermal limits and different representations of the thermal environment for different periods of time. Shown below are the correlation coefficients for these relationships. Each facet shows the relationship for a different dimension of the thermal environment. Correlation coefficients are plotted for different durations, for species that were collected more than five times. Only data for mature female copepods was included.

We can see that, in general, copepods are responding to proximate cues from the thermal environment, with correlations generally dropping off substantially as acclimation window duration increases. An exception is Epischura lacustris, which appears to be responding to maximum temperatures experienced over a 20 day time period.

### Pulling predictors and measuring correlations for much finer timescales; 1-56 days

words_to_numbers <- function(s) {
  s <- stringr::str_to_lower(s)
  for (i in 0:56)
    s <- stringr::str_replace_all(s, words(i), as.character(i))
  s
}

num_colls = full_data %>% 
  filter(sex == "female") %>% 
  select(collection_date, sp_name) %>%  
  distinct() %>%  
  count(sp_name) %>% 
  filter(n >= 5)

corr_vals = data.frame()

dur_vals = c(2, 3, 4, 5, 10, 15, 20, 25, 30)
for(i in dur_vals){
  
  duration_temps = get_predictors(daily_values = daily_temp_data, 
                             raw_temp = temp_data, 
                             n_days = i) %>% 
    filter(date %in% as_date(unique(full_data$collection_date)))
  
  corr_data = full_data %>%
    filter(sp_name %in% num_colls$sp_name) %>% 
    filter(sex == "female") %>% 
    mutate(collection_date = as.Date(collection_date)) %>% 
    inner_join(duration_temps, join_by(collection_date == date)) %>% 
    pivot_longer(cols = c(collection_temp, contains("day_")),
                 values_to = "value", 
                 names_to = "predictor") %>%  
    group_by(sp_name, predictor) %>% 
    summarise(correlation = cor.test(ctmax, value)$estimate,
              p.value = cor.test(ctmax, value)$p.value,
              ci_low = cor.test(ctmax, value)$conf.int[1],
              ci_high = cor.test(ctmax, value)$conf.int[2]) %>% 
    filter(predictor != "collection_temp") %>% 
    mutate(sig = ifelse(p.value <0.05, "Sig.", "Non Sig.")) %>% 
    separate(predictor, "_day_", into = c(NA, "parameter")) %>% 
    mutate(duration = i)
  
  corr_vals = bind_rows(corr_vals, corr_data)
}

corr_vals = corr_vals %>%  
  mutate(duration = as.numeric(duration))
corr_vals %>% 
mutate(parameter = fct_relevel(parameter, c("min", "max", "range",
                                            "mean", "med", "var",
                                            "mean_min", "mean_max", "mean_range"))) %>% 
ggplot(aes(x = duration, y = correlation, colour = sp_name)) + 
  facet_wrap(.~parameter) + 
  geom_hline(yintercept = 0) + 
  geom_line(linewidth = 1) + 
  scale_colour_manual(values = species_cols) + 
  labs(x = "Duration (days)",
       y = "Correlation", 
       colour = "Species") + 
  theme_matt_facets()

Shown here are the top three factors for each species.

# 
# corr_vals = full_data %>%
#   filter(sp_name %in% num_colls$sp_name) %>% 
#   filter(sex == "female") %>% 
#   mutate(collection_date = as.Date(collection_date)) %>% 
#   full_join(temp_predictors, join_by(collection_date == date)) %>% 
#   pivot_longer(cols = c(collection_temp, mean_temp:tail(names(.), 1)),
#                values_to = "value", 
#                names_to = "predictor") %>%  
#   group_by(sp_name, predictor) %>% 
#   summarise(correlation = cor.test(ctmax, value)$estimate,
#             p.value = cor.test(ctmax, value)$p.value,
#             ci_low = cor.test(ctmax, value)$conf.int[1],
#             ci_high = cor.test(ctmax, value)$conf.int[2]) %>% 
#   mutate(sig = ifelse(p.value <0.05, "Sig.", "Non Sig."))

corr_vals %>%  
  filter(sig == "Sig.") %>% 
  drop_na(correlation) %>% 
  group_by(sp_name) %>%
  arrange(desc(correlation)) %>% 
  slice_head(n = 3) %>% 
  select("Species" = sp_name, "Predictor" = parameter, "Duration" = duration, "Correlation" = correlation, "P-Value" = p.value) %>% 
  knitr::kable(align = "c")
Species Predictor Duration Correlation P-Value
Epischura lacustris max 20 0.8018430 0e+00
Epischura lacustris max 15 0.7551468 2e-07
Epischura lacustris med 5 0.7298558 7e-07
Leptodiaptomus minutus max 10 0.6230675 0e+00
Leptodiaptomus minutus mean_max 3 0.6213961 0e+00
Leptodiaptomus minutus mean_max 4 0.6209112 0e+00
Skistodiaptomus oregonensis max 2 0.5478622 0e+00
Skistodiaptomus oregonensis mean_max 2 0.5444970 0e+00
Skistodiaptomus oregonensis mean_max 3 0.5426651 0e+00

Trait Variation

# ctmax_plot = full_data %>% 
#   mutate( #sp_name = str_replace(sp_name, pattern = " ",
#     #                              replacement = "\n"),
#     sp_name = fct_reorder(sp_name, ctmax, mean)) %>% 
#   ggplot(aes(y = sp_name, x = ctmax)) + 
#   geom_point(aes(colour= sp_name_sub),
#              position = position_dodge(width = 0.3),
#              size = 4) + 
#   scale_colour_manual(values = species_cols) + 
#   xlab(NULL) + 
#   labs(y = "",
#        x = "CTmax (°C)",
#        colour = "Group") + 
#   theme_matt() + 
#   theme(legend.position = "none")
# 
# size_plot = full_data %>% 
#   mutate(sp_name = fct_reorder(sp_name, ctmax, mean)) %>% 
#   ggplot(aes(y = sp_name, x = size)) + 
#   geom_point(aes(colour= sp_name_sub),
#              position = position_dodge(width = 0.3),
#              size = 4) + 
#   scale_colour_manual(values = species_cols) + 
#   labs(x = "Prosome Length (mm)",
#        y = "", 
#        colour = "Group") + 
#   guides(color = guide_legend(ncol = 1)) +
#   theme_matt(base_size = ) + 
#   theme(legend.position = "right",
#         axis.text.y = element_blank(),
#         plot.margin = margin(0, 0, 0, 0,"cm"))
# 
# trait_plot = ctmax_plot + size_plot
# trait_plot

Shown below are the distributions of thermal limits for each species. This includes all data (all collections, stages, sexes, etc.). It’s clear that there is substantial variation in thermal limits for several species.

Shown below are the clutch size distributions for the three diaptomiid species, which produce egg sacs that allow for easy quantification of fecundity.

full_data %>%  
  drop_na(fecundity) %>%  
  ggplot(aes(x = fecundity, fill = sp_name_sub)) + 
  facet_wrap(.~sp_name_sub, ncol = 1) + 
  geom_histogram(binwidth = 2) + 
  scale_fill_manual(values = species_cols) + 
  labs(x = "Fecundity (# Eggs)") +
  theme_matt_facets() + 
  theme(legend.position = "none")

One of the main aims of this project is to examine the patterns and processes driving variation in upper thermal limits across these species of copepods.

Variation with temperature

We expect one of the primary drivers of copepod thermal limits to be temperature. The correlation analysis has shown that the copepods are generally (although not always) responding to the recent thermal environment. Shown below are thermal limits, body size, and fecundity values plotted against the temperature at the time of collection. Also shown is warming tolerance, calculated as the difference between upper thermal limit and the collection temperature.

We generally see an increase in thermal limits with increasing collection temperature, a slight decrease in body size, and variable relationships between temperature and fecundity. All species maintained some degree of buffer between environmental temperatures and upper thermal limits, but Epischura and L. minutus approached their upper thermal limits during the warmest collections during the summer.

ctmax_temp = ggplot(full_data, aes(x = collection_temp, y = ctmax, colour = sp_name)) + 
  geom_smooth(method = "lm", linewidth = 3) +
  geom_point(size = 3) + 
  labs(x = "Collection Temperature (°C)", 
       y = "CTmax (°C)",
       colour = "Species") + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "right")

size_temp = ggplot(filter(full_data, sex != "juvenile"), aes(x = collection_temp, y = size, colour = sp_name)) + 
  geom_smooth(method = "lm", linewidth = 3) +
  geom_point(size = 3) + 
  labs(x = "Collection Temperature (°C)", 
       y = "Length (mm)",
       colour = "Species")  + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "right")

wt_temp = ggplot(full_data, aes(x = collection_temp, y = warming_tol, colour = sp_name)) + 
  geom_smooth(method = "lm", linewidth = 3) +
  geom_point(size = 3) + 
  labs(x = "Collection Temperature (°C)", 
       y = "Warming Tolerance (°C)",
       colour = "Species")  + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "right")

eggs_temp = ggplot(full_data, aes(x = collection_temp, y = fecundity, colour = sp_name)) + 
  geom_smooth(method = "lm", linewidth = 3) +
  geom_point(size = 3) + 
  labs(x = "Collection Temperature (°C)", 
       y = "Fecundity (# Eggs)",
       colour = "Species")  + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "right")

ggarrange(ctmax_temp, size_temp, wt_temp, eggs_temp, 
          common.legend = T, legend = "right")

full_data %>% 
  #filter(sex == "female") %>%  
  group_by(sp_name) %>% filter(n() > 5) %>% filter(!str_detect(sp_name, pattern = "kindti")) %>% 
  ggplot(aes(x = collection_temp, y = ctmax, colour = sp_name)) + 
  facet_wrap(sp_name~.) + 
  geom_point(size = 2, alpha = 0.8) + 
  geom_smooth(method = "lm", se = F, linewidth = 2) + 
  labs(x = "Collection Temp. (°C)", 
       y = "CTmax (°C)") + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "none")

Copepods spent several days in lab during experiments. Shown below are the CTmax residuals (taken from a model of CTmax against collection temperature) plotted against the time spent in lab before measurements were made. We can see clearly that thermal limits are fairly stable over time.

ggplot(ctmax_resids, aes(x = days_in_lab, y = resids, colour = sp_name)) + 
  facet_wrap(sp_name~.) + 
  geom_point(size = 4, alpha = 0.5) + 
  geom_smooth(method = "lm", se = F, linewidth = 2) + 
  scale_x_continuous(breaks = c(0:5)) + 
  labs(x = "Days in lab", 
       y = "CTmax Residuals") + 
  scale_colour_manual(values = species_cols) + 
  theme_matt_facets() + 
  theme(legend.position = "none")

The term “acclimation response ratio” is often used to describe the effect of temperature on thermal limits. The ARR is calculated as the change in thermal limits per degree change in acclimation temperature. For our data, we will estimate ARR as the slope of CTmax against collection temperature.

coef_model_data = full_data %>% 
  group_by(sp_name, sex) %>% 
  filter(n() > 5 & !str_detect(sp_name, pattern = "kindti")) 

coef_n = full_data %>% 
  group_by(sp_name, sex) %>% 
  filter(n() > 5) %>% 
  summarise(sample_n = n(), 
            mean_ctmax = mean(ctmax))

ARR_vals = coef_model_data %>% 
  do(broom::tidy(lm(ctmax ~ collection_temp, data = .))) %>% 
  filter(term != "(Intercept)") %>% 
  select(sp_name, sex, "ARR" = estimate, std.error) %>% 
  arrange(ARR) %>% 
  inner_join(coef_n, by = c("sp_name", "sex"))
  
ARR_vals %>% 
  select("Species" = sp_name, 
         "Group" = sex, 
         "N" = sample_n,
         ARR, 
         "Error" = std.error) %>% 
  knitr::kable()
Species Group N ARR Error
Epischura lacustris juvenile 18 0.0573593 0.0974497
Skistodiaptomus oregonensis female 167 0.1771861 0.0221978
Epischura lacustris male 12 0.2039977 0.0410498
Leptodiaptomus minutus female 175 0.2042736 0.0202983
Leptodiaptomus minutus male 31 0.2068073 0.0251894
Leptodiaptomus minutus juvenile 8 0.2305062 0.0677669
Epischura lacustris female 35 0.2449800 0.0416285
Leptodiaptomus sicilis female 28 0.3001364 0.1793989
Skistodiaptomus oregonensis male 27 0.3397684 0.0475937
Skistodiaptomus oregonensis juvenile 14 0.3900367 0.0935739
coef_plot = ARR_vals %>% 
  mutate("abbr" = case_when(
    sp_name == "Epischura lacustris" ~ "E. lac",
    sp_name == "Leptodiaptomus minutus" ~ "L. min", 
    sp_name == "Skistodiaptomus oregonensis" ~ "S. ore",
    sp_name == "Leptodiaptomus sicilis" ~ "L. sic"
  )) %>% 
  ggplot(aes(x = abbr, y = ARR, colour = sp_name, shape = sex)) + 
  geom_errorbar(aes(ymin = ARR - std.error, ymax = ARR + std.error),
                width = 0.35, linewidth = 1, position = position_dodge(width = 0.5)) + 
  geom_point(size = 5,
    position = position_dodge(width = 0.5)) + 
  scale_colour_manual(values = species_cols) + 
  guides(colour = "none") + 
  labs(x = "Species", 
       y = "ARR", 
       shape = "Group") + 
  theme_matt() + 
  theme(legend.position = "right")

coef_lim_plot = ggplot(ARR_vals, aes(x = mean_ctmax, y = ARR)) + 
  geom_smooth(method = "lm", colour = "grey70", se = F, linewidth = 2) + 
  geom_errorbar(aes(colour = sp_name, ymin = ARR - std.error, ymax = ARR + std.error),
                width = 0.5, linewidth = 1, position = position_dodge(width = 0.5)) + 
  geom_point(aes(colour = sp_name, shape = sex ),
             size = 5,
    position = position_dodge(width = 0.5)) +
  scale_colour_manual(values = species_cols) + 
  guides(colour = "none") + 
  labs(x = "Mean CTmax (°C)", 
       y = "ARR", 
       shape = "Group") + 
  theme_matt() + 
  theme(legend.position = "right")

ggarrange(coef_plot, coef_lim_plot, common.legend = T, legend = "right")

Sex and stage variation in thermal limits

Previous sections have generally lumped juvenile, female, and male individuals together. There may be important stage- or sex-specific differences in CTmax though. For several species, we have measurements for individuals in different stages or of different sexes.

sex_sample_sizes = ctmax_resids %>%  
  group_by(sp_name, sex) %>%  
  summarise(num = n()) %>%  
  pivot_wider(id_cols = sp_name,
              names_from = sex, 
              values_from = num,
              values_fill = 0) %>% 
  select("Species" = sp_name, "Juvenile" = juvenile, "Female" = female, "Male" = male)

knitr::kable(sex_sample_sizes, align = "c")
Species Juvenile Female Male
Epischura lacustris 18 35 12
Leptodiaptomus minutus 7 175 31
Leptodiaptomus sicilis 0 28 5
Limnocalanus macrurus 2 5 1
Osphranticum labronectum 0 1 0
Senecella calanoides 0 1 0
Skistodiaptomus oregonensis 14 166 27

The female-male and female-juvenile comparisons show that there are generally no differences in thermal limits between these groups.

ctmax_resids %>% 
  filter(sp_name %in% filter(sex_sample_sizes, Male > 0, Female > 0)$Species & 
           sex != "juvenile") %>% 
  ggplot(aes(x = sex, y = resids, colour = sp_name, group = sp_name)) + 
  facet_wrap(sp_name~., ncol = 2) + 
  geom_smooth(method = "lm", se = F, linewidth = 1) + 
  geom_point(size = 3,
             alpha = 0.5,
             position = position_jitter(height = 0, width = 0.05)) +  
  labs(x = "Sex", 
       y = "CTmax Residuals") + 
  scale_colour_manual(values = species_cols) + 
  theme_bw(base_size = 18) + 
  theme(legend.position = "none", 
        panel.grid = element_blank())

ctmax_resids %>% 
  filter(sp_name %in% filter(sex_sample_sizes, Juvenile > 0 & Female > 0)$Species & 
           sex != "male") %>% 
  ggplot(aes(x = sex, y = resids, colour = sp_name, group = sp_name)) + 
  facet_wrap(sp_name~., ncol = 1) + 
  geom_smooth(method = "lm", se = F, linewidth = 1) + 
  geom_point(size = 3,
             alpha = 0.5,
             position = position_jitter(height = 0, width = 0.05)) +  
  labs(x = "Sex", 
       y = "CTmax (°C)") + 
  scale_colour_manual(values = species_cols) + 
  theme_bw(base_size = 18) + 
  theme(legend.position = "none", 
        panel.grid = element_blank())

Trait Correlations and Trade-offs

A relationship between size and upper thermal limits has been suggested in a wide range of other taxa. Shown below are the measured upper thermal limits plotted against prosome length. The overall relationship (inclusive of all species) is shown as the black line in the background. Regressions for each individual species are also shown. For the three diaptomids and Epischura there is a slight negative relationship between size and thermal limits. However, across the entire assemblage, there is a slight increase in thermal limits with increasing size. This may, however, be due to the relative overrepresentation of larger summer species like Skistodiaptomus. Increasing the measurements on larger, cold-water species like L. sicilis and Limnocalanus may alter this observed pattern.


full_data %>% 
  #filter(sex == "female") %>%  
  ggplot( aes(x = size, y = ctmax, colour = sp_name)) + 
  geom_smooth(data = full_data, 
              aes(x = size, y = ctmax),
              method = "lm", 
              colour ="black", 
              linewidth = 2.5) + 
  geom_point(size = 2, alpha = 0.8) + 
  geom_smooth(method = "lm", se = F, linewidth = 2) + 
  labs(x = "Length (mm)", 
       y = "CTmax (°C)",
       colour = "Species") + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "right")

Shown here is the relationship for each species individually.

full_data %>% 
  #filter(sex == "female") %>%  
  group_by(sp_name) %>% filter(n() >2) %>% filter(!str_detect(sp_name, pattern = "kindti")) %>% 
  ggplot( aes(x = size, y = ctmax, colour = sp_name)) + 
  facet_wrap(sp_name~., scales = "free", nrow = 2) + 
  geom_point(size = 2, alpha = 0.8) + 
  geom_smooth(method = "lm", se = F, linewidth = 2) + 
  labs(x = "Length (mm)", 
       y = "CTmax (°C)",
       colour = "Species") + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "none")

full_data %>% 
  group_by(sp_name, sex) %>% 
  summarize(mean_ctmax = mean(ctmax, na.rm = T),
            mean_size = mean(size, na.rm = T)) %>% 
  #filter(sex == "female") %>% 
  ggplot(aes(x = mean_size, y = mean_ctmax)) + 
  geom_smooth(method = "lm", se = F, linewidth = 2, colour = "black") + 
  geom_point(aes(colour = sp_name, shape = sex),
             size = 5) + 
  labs(x = "Length (mm)", 
       y = "CTmax (°C)",
       colour = "Species") + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "right")

Shown here is the relationship between fecundity and size, showing the classic pattern of increasing egg production with increasing size.

ctmax_resids %>%  
  drop_na(fecundity) %>% 
ggplot(aes(x = size, y = fecundity, colour = sp_name)) + 
  geom_smooth(method = "lm", se = F, linewidth = 2) + 
  geom_point(size = 2, alpha = 0.5) + 
  labs(x = "Prosome length (mm)", 
       y = "Fecundity (# Eggs)",
       colour = "Species") + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "right")

Individuals may also allocate energy to different fitness related traits, prioritizing reproductive output over environmental tolerance, for example. Shown below is the relationship between CTmax residuals (again, controlling for the effects of collection temperature) against fecundity. We can see clearly that individuals with increased fecundity are not decreasing thermal limits, suggesting that there is no energetic trade-off between these traits.

ctmax_resids %>%  
  drop_na(fecundity) %>% 
  ggplot(aes(y = resids, x = fecundity, colour = sp_name)) + 
  geom_smooth(method = "lm", se = F, linewidth = 2) + 
  geom_point(size = 2, alpha = 0.5) + 
  labs(y = "CTmax (°C)", 
       x = "Fecundity (# Eggs)") + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "right")

if(predict_vuln == F){
  knitr::knit_exit()
}
LS0tCnRpdGxlOiBTZWFzb25hbGl0eSBpbiBMYWtlIENoYW1wbGFpbiBDb3BlcG9kIFRoZXJtYWwgTGltaXRzCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgICAgICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICAgICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICAgICAgICB0b2M6IHRydWUKICAgICAgICAgIHRvY19mbG9hdDogdHJ1ZQogIGdpdGh1Yl9kb2N1bWVudDoKICAgICAgICAgIGh0bWxfcHJldmlldzogZmFsc2UKICAgICAgICAgIHRvYzogdHJ1ZQogICAgICAgICAgdG9jX2RlcHRoOiAzCi0tLQoKYGBge3IgdG8tZG99CiMjIyBUbyBEbyAKCiMgQWN0dWFsIHN0YXRpc3RpY3MgZm9yIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiB0ZW1wZXJhdHVyZSBhbmQgQ1RtYXgsIHNpemUsIGFuZCBmZWN1bmRpdHkKIyBQdWxsIHJlc2lkdWFscyBmcm9tIENUbWF4IH4gdGVtcGVyYXR1cmUgbW9kZWwsIGFuZCBleGFtaW5lIHRoZSBjaGFuZ2Ugb3ZlciB0aW1lIGluIGxhYiBhbmQgdGhlIHJlbGF0aW9uc2hpcCB3aXRoIGZlY3VuZGl0eQoKYGBgCgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9VCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGLCBlY2hvID0gRn0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBrbml0cjo6aXNfaHRtbF9vdXRwdXQoKSwKICBmaWcuYWxpZ24gPSAiY2VudGVyIiwKICBmaWcucGF0aCA9ICIuLi9GaWd1cmVzL21hcmtkb3duLyIsCiAgZGV2ID0gYygicG5nIiwgInBkZiIpLAogIG1lc3NhZ2UgPSBGQUxTRSwKICB3YXJuaW5nID0gRkFMU0UsCiAgY29sbGFwc2UgPSBUCikKCnRoZW1lX21hdHQgPSBmdW5jdGlvbihiYXNlX3NpemUgPSAxOCwKICAgICAgICAgICAgICAgICAgICAgIGRhcmtfdGV4dCA9ICJncmV5MjAiKXsKICBtaWRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzJdCiAgbGlnaHRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzNdCiAgCiAgZ2dwdWJyOjp0aGVtZV9wdWJyKGJhc2VfZmFtaWx5PSJzYW5zIikgJStyZXBsYWNlJSAKICAgIHRoZW1lKAogICAgICBwYW5lbC5iYWNrZ3JvdW5kICA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksIAogICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLCAKICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLAogICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwKICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSBtaWRfdGV4dCwgbGluZWhlaWdodCA9IDEuMSksCiAgICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAxLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IGRhcmtfdGV4dCksCiAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gbWlkX3RleHQpLAogICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDEuMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IHVuaXQoYygzLCAwLCAwLCAwKSwgIm1tIikpLAogICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDEuMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IHVuaXQoYygwLCA1LCAwLCAwKSwgIm1tIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5nbGUgPSA5MCksCiAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9YmFzZV9zaXplICogMC45KSwKICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAwLjksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjZSA9ICJib2xkIiksCiAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDAuMjUsIDAuMjUsIDAuMjUsIDAuMjUsImNtIikKICAgICkKfQoKdGhlbWVfbWF0dF9mYWNldHMgPSBmdW5jdGlvbihiYXNlX3NpemUgPSAxOCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXJrX3RleHQgPSAiZ3JleTIwIil7CiAgbWlkX3RleHQgPC0gIG1vbm9jaHJvbWVSOjpnZW5lcmF0ZV9wYWxldHRlKGRhcmtfdGV4dCwgImdvX2xpZ2h0ZXIiLCBuX2NvbG91cnMgPSA1KVsyXQogIGxpZ2h0X3RleHQgPC0gIG1vbm9jaHJvbWVSOjpnZW5lcmF0ZV9wYWxldHRlKGRhcmtfdGV4dCwgImdvX2xpZ2h0ZXIiLCBuX2NvbG91cnMgPSA1KVszXQogIAogIHRoZW1lX2J3KGJhc2VfZmFtaWx5PSJzYW5zIikgJStyZXBsYWNlJSAKICAgIHRoZW1lKAogICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAogICAgICBwYW5lbC5iYWNrZ3JvdW5kICA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksIAogICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLCAKICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLAogICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwKICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSBtaWRfdGV4dCwgbGluZWhlaWdodCA9IDEuMSksCiAgICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplKSwKICAgICAgdGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDEuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gZGFya190ZXh0KSwKICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBtaWRfdGV4dCksCiAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMS4yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDMsIDAsIDAsIDApLCAibW0iKSksCiAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMS4yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDAsIDUsIDAsIDApLCAibW0iKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbmdsZSA9IDkwKSwKICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT1iYXNlX3NpemUgKiAwLjkpLAogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDAuOSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlID0gImJvbGQiKSwKICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMC4yNSwgMC4yNSwgMC4yNSwgMC4yNSwiY20iKQogICAgKQp9CgpzcGVjaWVzX2NvbHMgPSBjKCJMZXB0b2RpYXB0b211cyBtaW51dHVzIiA9ICIjZmZkMDI5IiwKICAgICAgICAgICAgICAgICAiTGVwdG9kaWFwdG9tdXMgbWludXR1cyBqdXZlbmlsZSIgPSAiI2UzZDhhZiIsCiAgICAgICAgICAgICAgICAgIkxlcHRvZGlhcHRvbXVzIG1pbnV0dXMgbWFsZSIgPSAiI2ZmZTg5NiIsCiAgICAgICAgICAgICAgICAgIkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMiID0gIiNEODZGMjkiLAogICAgICAgICAgICAgICAgICJMZXB0b2RpYXB0b211cyBzaWNpbGlzIG1hbGUiID0gIiNFMjhDMDAiLAogICAgICAgICAgICAgICAgICJTa2lzdG9kaWFwdG9tdXMgb3JlZ29uZW5zaXMiID0gIiNDNUMzNUEiLAogICAgICAgICAgICAgICAgICJTa2lzdG9kaWFwdG9tdXMgb3JlZ29uZW5zaXMgbWFsZSIgPSAiI2U2ZTZhYSIsIAogICAgICAgICAgICAgICAgICJFcGlzY2h1cmEgbGFjdXN0cmlzIGp1dmVuaWxlIiA9ICJwbHVtMSIsIAogICAgICAgICAgICAgICAgICJFcGlzY2h1cmEgbGFjdXN0cmlzIG1hbGUiID0gInBsdW0zIiwgCiAgICAgICAgICAgICAgICAgIkVwaXNjaHVyYSBsYWN1c3RyaXMiID0gInBsdW00IiwgCiAgICAgICAgICAgICAgICAgIkxpbW5vY2FsYW51cyBtYWNydXJ1cyIgPSAic2t5Ymx1ZTQiLCAKICAgICAgICAgICAgICAgICAiTGltbm9jYWxhbnVzIG1hY3J1cnVzIG1hbGUiID0gInNreWJsdWUzIiwgCiAgICAgICAgICAgICAgICAgIkxpbW5vY2FsYW51cyBtYWNydXJ1cyBqdXZlbmlsZSIgPSAic2t5Ymx1ZSIsIAogICAgICAgICAgICAgICAgICJTZW5lY2VsbGEgY2FsYW5vaWRlcyIgPSAiZGFya3NlYWdyZWVuMyIsCiAgICAgICAgICAgICAgICAgIkxlcHRvZG9yYSBraW5kdGkgbWFsZSIgPSAibGlnaHRibHVlMyIsCiAgICAgICAgICAgICAgICAgIkxlcHRvZG9yYSBraW5kdGkiID0gImxpZ2h0Ymx1ZTQiLAogICAgICAgICAgICAgICAgICJMZXB0b2RvcmEga2luZHRpIGp1dmVuaWxlIiA9ICJsaWdodGJsdWUiLAogICAgICAgICAgICAgICAgICJPc3BocmFudGljdW0gbGFicm9uZWN0dW0iID0gImxpZ2h0Y29yYWwiKQpgYGAKCiMjIENvcGVwb2QgQ29sbGVjdGlvbgoKQ29wZXBvZHMgd2VyZSBjb2xsZWN0ZWQgYXQgYXBwcm94aW1hdGVseSB3ZWVrbHkgaW50ZXJ2YWxzIGZyb20gTGFrZSBDaGFtcGxhaW4gKEJ1cmxpbmd0b24gRmlzaGluZyBQaWVyKS4gUGxhbmt0b24gd2FzIGNvbGxlY3RlZCBmcm9tIHRoZSB0b3AgMyBtZXRlcnMgdXNpbmcgYSAyNTAgdW0gbWVzaCBuZXQuIAoKYGBge3J9CiMgTGFrZSBDaGFtcGxhaW4gbmVhciBCdXJsaW5ndG9uLCBWVApzaXRlTnVtYmVyID0gIjA0Mjk0NTAwIgpDaGFtcGxhaW5JbmZvID0gcmVhZE5XSVNzaXRlKHNpdGVOdW1iZXIpCnBhcmFtZXRlckNkID0gIjAwMDEwIgpzdGFydERhdGUgPSAiMjAyMy0wMS0wMSIKZW5kRGF0ZSA9ICIiCiNzdGF0Q2QgPSBjKCIwMDAwMSIsICIwMDAwMiIsIjAwMDAzIiwgIjAwMDExIikgIyAxIC0gbWF4LCAyIC0gbWluLCAzID0gbWVhbgoKIyBDb25zdHJ1Y3RzIHRoZSBVUkwgZm9yIHRoZSBkYXRhIHdhbnRlZCB0aGVuIGRvd25sb2FkcyB0aGUgZGF0YQp1cmwgPSBjb25zdHJ1Y3ROV0lTVVJMKHNpdGVOdW1iZXJzID0gc2l0ZU51bWJlciwgcGFyYW1ldGVyQ2QgPSBwYXJhbWV0ZXJDZCwgCiAgICAgICAgICAgICAgICAgICAgICAgc3RhcnREYXRlID0gc3RhcnREYXRlLCBlbmREYXRlID0gZW5kRGF0ZSwgc2VydmljZSA9ICJ1diIpCgp0ZW1wX2RhdGEgPSBpbXBvcnRXYXRlck1MMSh1cmwsIGFzRGF0ZVRpbWUgPSBUKSAlPiUgCiAgbXV0YXRlKCJkYXRlIiA9IGFzLkRhdGUoZGF0ZVRpbWUpKSAlPiUgCiAgc2VsZWN0KGRhdGUsICJ0ZW1wIiA9IFhfMDAwMTBfMDAwMDApCmBgYAoKQ29sbGVjdGlvbnMgYmVnYW4gaW4gbGF0ZSBNYXkgMjAyMy4gU2V2ZXJhbCBnYXBzIGFyZSBwcmVzZW50LCBidXQgY29sbGVjdGlvbnMgaGF2ZSBjb250aW51ZWQgYXQgcm91Z2hseSB3ZWVrbHkgaW50ZXJ2YWxzIHNpbmNlIHRoZW4uIENvcGVwb2RzIGZyb20gYHIgbGVuZ3RoKHVuaXF1ZShmdWxsX2RhdGEkY29sbGVjdGlvbl9kYXRlKSlgIGNvbGxlY3Rpb25zIHdlcmUgdXNlZCB0byBtYWtlIGEgdG90YWwgb2YgYHIgZGltKGZ1bGxfZGF0YSlbMV1gIHRoZXJtYWwgbGltaXQgbWVhc3VyZW1lbnRzLiBPdmVyIHRoaXMgdGltZSBwZXJpb2QsIGNvbGxlY3Rpb24gdGVtcGVyYXR1cmVzIHJhbmdlZCBmcm9tIGByIHBhc3RlKG1pbihmdWxsX2RhdGEkY29sbGVjdGlvbl90ZW1wKSwgIiB0byAiLCBtYXgoZnVsbF9kYXRhJGNvbGxlY3Rpb25fdGVtcCksIHNlcCA9ICIiKWDCsEMuICAgICAKClRoZXJlIGlzIHN1YnN0YW50aWFsIHZhcmlhdGlvbiBpbiB0aGVybWFsIGxpbWl0cyBhY3Jvc3MgdGhlIHNwZWNpZXMgY29sbGVjdGVkLiBUaGVyZSBpcyBhbHNvIHNvbWUgZGVncmVlIG9mIHZhcmlhdGlvbiB3aXRoaW4gdGhlIHNwZWNpZXMsIHdpdGggdGhlcm1hbCBsaW1pdHMgaW5jcmVhc2luZyBzbGlnaHRseSBkdXJpbmcgdGhlIHN1bW1lci4gICAgCgpgYGB7ciBjdG1heC10aW1lc2VyaWVzLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NX0KIyMgRGFpbHkgdmFsdWVzIGZvciB0aGUgcGVyaW9kIGV4YW1pbmVkIGJ5IGRhdGFzZXQKY29sbGVjdGlvbl9jb25kaXRpb25zID0gdGVtcF9kYXRhICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lIAogIHN1bW1hcmlzZShtZWFuX3RlbXAgPSBtZWFuKHRlbXApLAogICAgICAgICAgICBtZWRfdGVtcCA9IG1lZGlhbih0ZW1wKSwKICAgICAgICAgICAgdmFyX3RlbXAgPSB2YXIodGVtcCksIAogICAgICAgICAgICBtaW5fdGVtcCA9IG1pbih0ZW1wKSwgCiAgICAgICAgICAgIG1heF90ZW1wID0gbWF4KHRlbXApKSAlPiUgCiAgbXV0YXRlKCJyYW5nZV90ZW1wIiA9IG1heF90ZW1wIC0gbWluX3RlbXAsCiAgICAgICAgIGRhdGUgPSBhcy5EYXRlKGRhdGUpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAgCiAgZmlsdGVyKGRhdGUgPj0gKG1pbihhcy5EYXRlKGZ1bGxfZGF0YSRjb2xsZWN0aW9uX2RhdGUpKSAtIDcpKQoKIyMgTWVhbiBmZW1hbGUgdGhlcm1hbCBsaW1pdHMgZm9yIGVhY2ggc3BlY2llcywgZ3JvdXBlZCBieSBjb2xsZWN0aW9uCnNwZWNpZXNfc3VtbWFyaWVzID0gZnVsbF9kYXRhICU+JSAgCiAgI2ZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICBncm91cF9ieShzcF9uYW1lLCBjb2xsZWN0aW9uX2RhdGUsIGNvbGxlY3Rpb25fdGVtcCkgJT4lICAKICBzdW1tYXJpc2UoIm1lYW5fY3RtYXgiID0gbWVhbihjdG1heCksCiAgICAgICAgICAgICJzYW1wbGVfc2l6ZSIgPSBuKCksCiAgICAgICAgICAgICJjdG1heF9zdF9lcnIiID0gKHNkKGN0bWF4KSAvIHNxcnQoc2FtcGxlX3NpemUpKSwKICAgICAgICAgICAgImN0bWF4X3ZhciIgPSB2YXIoY3RtYXgpLCAKICAgICAgICAgICAgIm1lYW5fc2l6ZSIgPSBtZWFuKHNpemUpLAogICAgICAgICAgICAic2l6ZV9zdF9lcnIiID0gKHNkKHNpemUpIC8gc3FydChzYW1wbGVfc2l6ZSkpLAogICAgICAgICAgICAic2l6ZV92YXIiID0gdmFyKHNpemUpKSAlPiUgIAogIHVuZ3JvdXAoKSAlPiUgCiAgY29tcGxldGUoc3BfbmFtZSwgY29sbGVjdGlvbl9kYXRlKSAlPiUgCiAgYXJyYW5nZShkZXNjKHNhbXBsZV9zaXplKSkKCmFkdWx0X3N1bW1hcmllcyA9IGZ1bGxfZGF0YSAlPiUgIAogIGZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICBncm91cF9ieShzcF9uYW1lLCBjb2xsZWN0aW9uX2RhdGUsIGNvbGxlY3Rpb25fdGVtcCkgJT4lICAKICBzdW1tYXJpc2UoIm1lYW5fY3RtYXgiID0gbWVhbihjdG1heCksCiAgICAgICAgICAgICJzYW1wbGVfc2l6ZSIgPSBuKCksCiAgICAgICAgICAgICJjdG1heF9zdF9lcnIiID0gKHNkKGN0bWF4KSAvIHNxcnQoc2FtcGxlX3NpemUpKSwKICAgICAgICAgICAgImN0bWF4X3ZhciIgPSB2YXIoY3RtYXgpLCAKICAgICAgICAgICAgIm1lYW5fc2l6ZSIgPSBtZWFuKHNpemUpLAogICAgICAgICAgICAic2l6ZV9zdF9lcnIiID0gKHNkKHNpemUpIC8gc3FydChzYW1wbGVfc2l6ZSkpLAogICAgICAgICAgICAic2l6ZV92YXIiID0gdmFyKHNpemUpKSAlPiUgIAogIHVuZ3JvdXAoKSAlPiUgCiAgY29tcGxldGUoc3BfbmFtZSwgY29sbGVjdGlvbl9kYXRlKSAlPiUgCiAgYXJyYW5nZShkZXNjKHNhbXBsZV9zaXplKSkKCgpnZ3Bsb3QoKSArIAogIGdlb21fdmxpbmUoZGF0YSA9IHVuaXF1ZShzZWxlY3QoZnVsbF9kYXRhLCBjb2xsZWN0aW9uX2RhdGUpKSwgCiAgICAgICAgICAgICBhZXMoeGludGVyY2VwdCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSksCiAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleTkwIiwKICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEpICsgCiAgZ2VvbV9saW5lKGRhdGEgPSBjb2xsZWN0aW9uX2NvbmRpdGlvbnMsIAogICAgICAgICAgICBhZXMoeCA9IGFzLkRhdGUoZGF0ZSksIHkgPSBtZWFuX3RlbXApLAogICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCAKICAgICAgICAgICAgbGluZXdpZHRoID0gMikgKyAKICAjIGdlb21fZXJyb3JiYXIoZGF0YSA9IHNwZWNpZXNfc3VtbWFyaWVzLAogICMgICAgICAgICAgICAgICBhZXMoeCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSwKICAjICAgICAgICAgICAgICAgICAgIHltaW4gPSBtZWFuX2N0bWF4IC0gY3RtYXhfc3RfZXJyLCB5bWF4ID0gbWVhbl9jdG1heCArIGN0bWF4X3N0X2VyciwKICAjICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IHNwX25hbWUpLAogICMgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMSksCiAgIyAgICAgICAgICAgICAgIHdpZHRoID0gNSwgbGluZXdpZHRoID0gMSkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGFkdWx0X3N1bW1hcmllcywgCiAgICAgICAgICAgICBhZXMoeCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSwgeSA9IG1lYW5fY3RtYXgsIGNvbG91ciA9IHNwX25hbWUsIHNpemUgPSBzYW1wbGVfc2l6ZSkpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgbGFicyh4ID0gIkRhdGUiLCAKICAgICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLCAKICAgICAgIGNvbG91ciA9ICJTcGVjaWVzIiwKICAgICAgIHNpemUgPSAiU2FtcGxlIFNpemUiKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKU2l6ZSBhbHNvIHZhcmllZCBib3RoIGJldHdlZW4gYW5kIHdpdGhpbiBzcGVjaWVzLiAKCmBgYHtyIHNpemUtdGltZXNlcmllcywgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTV9CmdncGxvdCgpICsgCiAgZ2VvbV92bGluZShkYXRhID0gdW5pcXVlKHNlbGVjdChmdWxsX2RhdGEsIGNvbGxlY3Rpb25fZGF0ZSkpLCAKICAgICAgICAgICAgIGFlcyh4aW50ZXJjZXB0ID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpKSwKICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5OTAiLAogICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IGNvbGxlY3Rpb25fY29uZGl0aW9ucywgCiAgICAgICAgICAgIGFlcyh4ID0gYXMuRGF0ZShkYXRlKSwgeSA9IG1lYW5fdGVtcCksCiAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIAogICAgICAgICAgICBsaW5ld2lkdGggPSAyKSArIAogICMgZ2VvbV9lcnJvcmJhcihkYXRhID0gc3BlY2llc19zdW1tYXJpZXMsCiAgIyAgICAgICAgICAgICAgIGFlcyh4ID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpLCAKICAjICAgICAgICAgICAgICAgICAgIHltaW4gPSBtZWFuX2N0bWF4IC0gY3RtYXhfc3RfZXJyLCB5bWF4ID0gbWVhbl9jdG1heCArIGN0bWF4X3N0X2VyciwKICAjICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IHNwX25hbWUpLAogICMgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMSksCiAgIyAgICAgICAgICAgICAgIHdpZHRoID0gNSwgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX3BvaW50KGRhdGEgPSBhZHVsdF9zdW1tYXJpZXMsIAogICAgICAgICAgICAgYWVzKHggPSBhcy5EYXRlKGNvbGxlY3Rpb25fZGF0ZSksIHkgPSBtZWFuX3NpemUgKiA0MCwgY29sb3VyID0gc3BfbmFtZSwgc2l6ZSA9IHNhbXBsZV9zaXplKSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxKSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMoCiAgICBuYW1lID0gIlRlbXBlcmF0dXJlIiwgIyBGZWF0dXJlcyBvZiB0aGUgZmlyc3QgYXhpcwogICAgc2VjLmF4aXMgPSBzZWNfYXhpcyh+Li80MCwgbmFtZT0iUHJvc29tZSBMZW5ndGggKG1tKSIpLCAjIEFkZCBhIHNlY29uZCBheGlzIGFuZCBzcGVjaWZ5IGl0cyBmZWF0dXJlcwogICAgYnJlYWtzID0gYygwLDUsMTAsMTUsMjAsMjUsMzApCiAgKSArIAogIGxhYnMoeCA9ICJEYXRlIiwgCiAgICAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwgCiAgICAgICBjb2xvdXIgPSAiU3BlY2llcyIpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCgpGb3IgdGhlIHRocmVlIHNwZWNpZXMgd2l0aCB0aGUgbW9zdCBkYXRhICgqU2tpc3RvZGlhcHRvbXVzKiwgKkwuIG1pbnV0dXMqLCAqRXBpc2NodXJhKiksIHNob3duIGJlbG93IGlzIENUbWF4IGFuZCBib2R5IHNpemUsIHBsb3R0ZWQgYWdhaW5zdCB0aGUgZGF5IG9mIHRoZSB5ZWFyIGZvciBlYWNoIHNleC9zdGFnZSBzZXBhcmF0ZWx5LiAKCmBgYHtyIHRyYWl0LWRveS1mZWF0dXJlLCBmaWcud2lkdGggPSAxNCwgZmlnLmhlaWdodCA9IDd9CmN0bWF4X2ZlYXR1cmUgPSBmdWxsX2RhdGEgJT4lICAKICBtdXRhdGUoZG95ID0geWRheShjb2xsZWN0aW9uX2RhdGUpKSAlPiUgCiAgZmlsdGVyKHNwX25hbWUgJWluJSBjKCJTa2lzdG9kaWFwdG9tdXMgb3JlZ29uZW5zaXMiLCAiTGVwdG9kaWFwdG9tdXMgbWludXR1cyIsICJFcGlzY2h1cmEgbGFjdXN0cmlzIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkb3ksIHkgPSBjdG1heCwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfZ3JpZChzcF9uYW1lfnNleCkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICBsYWJzKHggPSAiRGF5IG9mIHRoZSBZZWFyIiwgCiAgICAgICB5ID0gIkNUbWF4ICjCsEMpIikgKyAKICBndWlkZXMoY29sb3IgPSBGQUxTRSkgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwMCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCgpzaXplX2ZlYXR1cmUgPSBmdWxsX2RhdGEgJT4lICAKICBtdXRhdGUoZG95ID0geWRheShjb2xsZWN0aW9uX2RhdGUpKSAlPiUgCiAgZmlsdGVyKHNwX25hbWUgJWluJSBjKCJTa2lzdG9kaWFwdG9tdXMgb3JlZ29uZW5zaXMiLCAiTGVwdG9kaWFwdG9tdXMgbWludXR1cyIsICJFcGlzY2h1cmEgbGFjdXN0cmlzIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkb3ksIHkgPSBzaXplLCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBmYWNldF9ncmlkKHNwX25hbWV+c2V4KSArIAogIGdlb21fcG9pbnQoKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIGxhYnMoeCA9ICJEYXkgb2YgdGhlIFllYXIiLCAKICAgICAgIHkgPSAiU2l6ZSAobW0pIikgKyAKICBndWlkZXMoY29sb3IgPSBGQUxTRSkgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwMCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCgpnZ2FycmFuZ2UoY3RtYXhfZmVhdHVyZSwgc2l6ZV9mZWF0dXJlLCBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gImJvdHRvbSIpCmBgYAoKCiMjIFRlbXBlcmF0dXJlIFZhcmlhYmlsaXR5Ckxha2UgQ2hhbXBsYWluIGlzIGhpZ2hseSBzZWFzb25hbCwgd2l0aCBib3RoIGF2ZXJhZ2UgdGVtcGVyYXR1cmVzIGFuZCB0ZW1wZXJhdHVyZSB2YXJpYWJpbGl0eSBjaGFuZ2luZyB0aHJvdWdob3V0IHRoZSB5ZWFyLiBUaGVzZSBwYXR0ZXJucyBpbiB0aGUgZXhwZXJpZW5jZWQgdGhlcm1hbCBlbnZpcm9ubWVudCBtYXkgZHJpdmUgdGhlIG9ic2VydmVkIHZhcmlhdGlvbiBpbiBjb3BlcG9kIHRoZXJtYWwgbGltaXRzLiBIb3dldmVyLCB0aGUgdGltZSBwZXJpb2QgYWZmZWN0aW5nIGNvcGVwb2QgdGhlcm1hbCBsaW1pdHMgaXMgdW5rbm93bi4gRGVwZW5kaW5nIHRoZSBvbiB0aGUgZHVyYXRpb24gb2YgdGltZSBjb25zaWRlcmVkLCB0aGVyZSBhcmUgbGFyZ2UgY2hhbmdlcyBpbiB0aGUgZXhwZXJpZW5jZWQgZW52aXJvbm1lbnQsIGluIHBhcnRpY3VsYXIgcmVnYXJkaW5nIHRoZSB0ZW1wZXJhdHVyZSByYW5nZSBhbmQgdmFyaWFuY2UuIENvbnNpZGVyIGZvciBleGFtcGxlIHRocmVlIHRpbWUgcGVyaW9kczogdGhlIGRheSBvZiBjb2xsZWN0aW9uLCBvbmUgd2VlayBwcmlvciB0byBjb2xsZWN0aW9uLCBhbmQgZm91ciB3ZWVrcyBwcmlvciB0byBjb2xsZWN0aW9uLiBXaGlsZSB0aGUgb3ZlcmFsbCBwYXR0ZXJuIGlzIHNpbWlsYXIsIHdlIGNhbiBzZWUgdGhhdCwgdW5zdXJwcmlzaW5nbHksIGNvbnNpZGVyaW5nIGxvbmdlciBwZXJpb2RzIG9mIHRpbWUgcmVzdWx0cyBpbiBsYXJnZXIgcmFuZ2VzIGFuZCBzbGlnaHRseSBjaGFuZ2VzIHRoZSBwYXR0ZXJuIG9mIHZhcmlhbmNlIGV4cGVyaWVuY2VkLiAKCmBgYHtyIGRhaWx5LXRlbXAtZGF0YX0KIyMgRGFpbHkgdmFsdWVzCmRhaWx5X3RlbXBfZGF0YSA9IHRlbXBfZGF0YSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGdyb3VwX2J5KGRhdGUpICU+JSAKICBzdW1tYXJpc2UobWVhbl90ZW1wID0gbWVhbih0ZW1wKSwKICAgICAgICAgICAgbWVkX3RlbXAgPSBtZWRpYW4odGVtcCksCiAgICAgICAgICAgIHZhcl90ZW1wID0gdmFyKHRlbXApLCAKICAgICAgICAgICAgbWluX3RlbXAgPSBtaW4odGVtcCksIAogICAgICAgICAgICBtYXhfdGVtcCA9IG1heCh0ZW1wKSkgJT4lIAogIG11dGF0ZSgicmFuZ2VfdGVtcCIgPSBtYXhfdGVtcCAtIG1pbl90ZW1wKQoKZGF5X3ByaW9yX3RlbXBfZGF0YSA9IHRlbXBfZGF0YSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBncm91cF9ieShkYXRlKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fdGVtcCA9IG1lYW4odGVtcCksCiAgICAgICAgICAgIG1lZF90ZW1wID0gbWVkaWFuKHRlbXApLAogICAgICAgICAgICB2YXJfdGVtcCA9IHZhcih0ZW1wKSwgCiAgICAgICAgICAgIG1pbl90ZW1wID0gbWluKHRlbXApLCAKICAgICAgICAgICAgbWF4X3RlbXAgPSBtYXgodGVtcCkpICU+JSAKICBtdXRhdGUoZGF0ZSA9IGRhdGUgKyAxKSAlPiUgCiAgcmVuYW1lX3dpdGgoLmZuID0gfiBwYXN0ZTAoInByaW9yX2RheV8iLCAueCksIC5jb2xzID0gYygtZGF0ZSkpCgpkYWlseV9wbG90ID0gZGFpbHlfdGVtcF9kYXRhICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGMoLWRhdGUpLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJwYXJhbWV0ZXIiLCAKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInRlbXAiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IHRlbXAsIGNvbG91ciA9IHBhcmFtZXRlcikpICsgCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDEpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKAogICAgIm1lYW5fdGVtcCIgPSAib2xpdmVkcmFiMyIsCiAgICAibWVkX3RlbXAiID0gInNlYWdyZWVuMyIsCiAgICAibWF4X3RlbXAiID0gInRvbWF0byIsICAKICAgICJtaW5fdGVtcCIgPSAiZG9kZ2VyYmx1ZSIsCiAgICAicmFuZ2VfdGVtcCIgPSAiZ29sZGVucm9kMyIsCiAgICAidmFyX3RlbXAiID0gImRhcmtnb2xkZW5yb2QxIgogICkpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGFzLkRhdGUoYygiMjAyMy0wMS0wMSIsICIyMDIzLTA0LTAxIiwgIjIwMjMtMDctMDEiKSkpICsgCiAgZ2d0aXRsZSgiRGFpbHkgVmFsdWVzIikgKyAKICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAogICAgICAgeCA9ICIiKSArIAogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDIwKSArIAogIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAyNzAsIGhqdXN0ID0gMCwgdmp1c3QgPSAwLjUpKQpgYGAKCmBgYHtyIHByZWRpY3RvcnMtZnVuY3Rpb259CiMjIERlZmluaW5nIHRoZSBmdW5jdGlvbiB0byBnZXQgcHJlZGljdG9yIHZhbHVlcyBmb3IgcGVyaW9kcyBvZiBkaWZmZXJlbnQgbGVuZ3RocwpnZXRfcHJlZGljdG9ycyA9IGZ1bmN0aW9uKGRhaWx5X3ZhbHVlcywgcmF3X3RlbXAsIG5fZGF5cyl7CiAgcHJlZml4ID0gc3RyX3JlcGxhY2VfYWxsKHhmdW46Om51bWJlcnNfdG9fd29yZHMobl9kYXlzKSwgcGF0dGVybiA9ICIgIiwgcmVwbGFjZW1lbnQgPSAiLSIpCiAgCiAgbWVhbl92YWx1ZXMgPSBkYWlseV92YWx1ZXMgJT4lIAogICAgdW5ncm91cCgpICU+JSAKICAgIG11dGF0ZShtZWFuX21heCA9IHNsaWRlX3ZlYygueCA9IG1heF90ZW1wLCAuZiA9IG1lYW4sIC5iZWZvcmUgPSBuX2RheXMsIC5jb21wbGV0ZSA9IFQpLAogICAgICAgICAgIG1lYW5fbWluID0gc2xpZGVfdmVjKC54ID0gbWluX3RlbXAsIC5mID0gbWVhbiwgLmJlZm9yZSA9IG5fZGF5cywgLmNvbXBsZXRlID0gVCksCiAgICAgICAgICAgbWVhbl9yYW5nZSA9IHNsaWRlX3ZlYygueCA9IHJhbmdlX3RlbXAsIC5mID0gbWVhbiwgLmJlZm9yZSA9IG5fZGF5cywgLmNvbXBsZXRlID0gVCkpICU+JSAKICAgIHNlbGVjdChkYXRlLCBtZWFuX21heCwgbWVhbl9taW4sIG1lYW5fcmFuZ2UpICU+JSAKICAgIHJlbmFtZV93aXRoKCB+IHBhc3RlKHByZWZpeCwgImRheSIsIC54LCBzZXAgPSAiXyIpLCAuY29scyA9IGMoLWRhdGUpKQogIAogIHBlcmlvZF92YWx1ZXMgPSByYXdfdGVtcCAlPiUgCiAgICBtdXRhdGUobWVhbiA9IHNsaWRlX2luZGV4X21lYW4odGVtcCwgaSA9IGRhdGUsIGJlZm9yZSA9IGRheXMobl9kYXlzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFfcm0gPSBUKSwKICAgICAgICAgICBtYXggPSBzbGlkZV9pbmRleF9tYXgodGVtcCwgaSA9IGRhdGUsIGJlZm9yZSA9IGRheXMobl9kYXlzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hX3JtID0gVCksCiAgICAgICAgICAgbWluID0gc2xpZGVfaW5kZXhfbWluKHRlbXAsIGkgPSBkYXRlLCBiZWZvcmUgPSBkYXlzKG5fZGF5cyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hX3JtID0gVCksCiAgICAgICAgICAgbWVkID0gc2xpZGVfaW5kZXhfZGJsKHRlbXAsIC5pID0gZGF0ZSwgLmJlZm9yZSA9IGRheXMobl9kYXlzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hX3JtID0gVCwgLmYgPSBtZWRpYW4pLAogICAgICAgICAgIHZhciA9IHNsaWRlX2luZGV4X2RibCh0ZW1wLCAuaSA9IGRhdGUsIC5iZWZvcmUgPSBkYXlzKG5fZGF5cyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZiA9IHZhciksCiAgICAgICAgICAgcmFuZ2UgPSBtYXggLSBtaW4pICU+JSAgCiAgICBzZWxlY3QoLXRlbXApICU+JSAgCiAgICBkaXN0aW5jdCgpICU+JSAKICAgIHJlbmFtZV93aXRoKCB+IHBhc3RlKHByZWZpeCwgImRheSIsIC54LCBzZXAgPSAiXyIpLCAuY29scyA9IGMoLWRhdGUpKSU+JSAKICAgIGlubmVyX2pvaW4obWVhbl92YWx1ZXMsIGJ5ID0gYygiZGF0ZSIpKSAlPiUgIAogICAgZHJvcF9uYSgpCiAgCiAgcmV0dXJuKHBlcmlvZF92YWx1ZXMpCn0KYGBgCgpgYGB7ciBwcmVkaWN0b3JzLWFuZC1wbG90cywgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTV9CiMgIyMgR2V0dGluZyBwcmVkaWN0b3IgdmFyaWFibGVzIGZvciBkaWZmZXJlbnQgcGVyaW9kcwojIAojICMjIyBTaG9ydCAodGhyZWUgZGF5cykKIyB0aHJlZV9kYXlfdGVtcHMgPSBnZXRfcHJlZGljdG9ycyhkYWlseV92YWx1ZXMgPSBkYWlseV90ZW1wX2RhdGEsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd190ZW1wID0gdGVtcF9kYXRhLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuX2RheXMgPSAzKQojIAojICMjIyBPTkUgV0VFSwp3ZWVrX3RlbXBzID0gZ2V0X3ByZWRpY3RvcnMoZGFpbHlfdmFsdWVzID0gZGFpbHlfdGVtcF9kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X3RlbXAgPSB0ZW1wX2RhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuX2RheXMgPSA3KQoKd2Vla19wbG90ID0gd2Vla190ZW1wcyAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoLWRhdGUpLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJwYXJhbWV0ZXIiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidGVtcCIpICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgJWluJSBjKCJzZXZlbl9kYXlfbWVhbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgInNldmVuX2RheV9tZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICJzZXZlbl9kYXlfbWF4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAic2V2ZW5fZGF5X21pbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgInNldmVuX2RheV92YXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICJzZXZlbl9kYXlfcmFuZ2UiKSkgJT4lCiAgbXV0YXRlKHBhcmFtZXRlciA9IHBhc3RlKHdvcmQocGFyYW1ldGVyLCBzdGFydCA9IDMsIHNlcCA9IGZpeGVkKCJfIikpLCAiX3RlbXAiLCBzZXAgPSAiIikpICU+JQogIGdncGxvdChhZXMoeCA9IGRhdGUsIHkgPSB0ZW1wLCBjb2xvdXIgPSBwYXJhbWV0ZXIpKSArCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDEpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoCiAgICAibWVhbl90ZW1wIiA9ICJvbGl2ZWRyYWIzIiwKICAgICJtZWRfdGVtcCIgPSAic2VhZ3JlZW4zIiwKICAgICJtYXhfdGVtcCIgPSAidG9tYXRvIiwKICAgICJtaW5fdGVtcCIgPSAiZG9kZ2VyYmx1ZSIsCiAgICAicmFuZ2VfdGVtcCIgPSAiZ29sZGVucm9kMyIsCiAgICAidmFyX3RlbXAiID0gImRhcmtnb2xkZW5yb2QxIgogICkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMuRGF0ZShjKCIyMDIzLTAxLTAxIiwgIjIwMjMtMDQtMDEiLCAiMjAyMy0wNy0wMSIpKSkgKwogIGdndGl0bGUoIk9uZSBXZWVrIikgKwogIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiAgICAgICB4ID0gIiIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAyMCkgKwogIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAyNzAsIGhqdXN0ID0gMCwgdmp1c3QgPSAwLjUpKQojIAojIAojICMjIyBUV08gV0VFS1MKIyB0d29fd2Vla190ZW1wcyA9IGdldF9wcmVkaWN0b3JzKGRhaWx5X3ZhbHVlcyA9IGRhaWx5X3RlbXBfZGF0YSwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfdGVtcCA9IHRlbXBfZGF0YSwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuX2RheXMgPSAxNCkKIyAKIyB0d29fd2Vla19wbG90ID0gdHdvX3dlZWtfdGVtcHMgJT4lIAojICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKC1kYXRlKSwKIyAgICAgICAgICAgICAgICBuYW1lc190byA9ICJwYXJhbWV0ZXIiLCAKIyAgICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidGVtcCIpICU+JSAKIyAgIGZpbHRlcihwYXJhbWV0ZXIgJWluJSBjKCJmb3VydGVlbl9kYXlfbWVhbiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm91cnRlZW5fZGF5X21lZCIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm91cnRlZW5fZGF5X21heCIsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvdXJ0ZWVuX2RheV9taW4iLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3VydGVlbl9kYXlfdmFyIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3VydGVlbl9kYXlfcmFuZ2UiKSkgJT4lIAojICAgbXV0YXRlKHBhcmFtZXRlciA9IHBhc3RlKHdvcmQocGFyYW1ldGVyLCBzdGFydCA9IDMsIHNlcCA9IGZpeGVkKCJfIikpLCAiX3RlbXAiLCBzZXAgPSAiIikpICU+JSAKIyAgIGdncGxvdChhZXMoeCA9IGRhdGUsIHkgPSB0ZW1wLCBjb2xvdXIgPSBwYXJhbWV0ZXIpKSArIAojICAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDEpICsgCiMgICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoCiMgICAgICJtZWFuX3RlbXAiID0gIm9saXZlZHJhYjMiLAojICAgICAibWVkX3RlbXAiID0gInNlYWdyZWVuMyIsCiMgICAgICJtYXhfdGVtcCIgPSAidG9tYXRvIiwgIAojICAgICAibWluX3RlbXAiID0gImRvZGdlcmJsdWUiLAojICAgICAicmFuZ2VfdGVtcCIgPSAiZ29sZGVucm9kMyIsCiMgICAgICJ2YXJfdGVtcCIgPSAiZGFya2dvbGRlbnJvZDEiCiMgICApKSArIAojICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGFzLkRhdGUoYygiMjAyMy0wMS0wMSIsICIyMDIzLTA0LTAxIiwgIjIwMjMtMDctMDEiKSkpICsgCiMgICBnZ3RpdGxlKCJUd28gV2Vla3MiKSArIAojICAgbGFicyh5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKIyAgICAgICAgeCA9ICIiKSArIAojICAgdGhlbWVfYncoYmFzZV9zaXplID0gMjApICsgCiMgICB0aGVtZShwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAojICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAyNzAsIGhqdXN0ID0gMCwgdmp1c3QgPSAwLjUpKQojIAojIAojICMjIyBGT1VSIFdFRUtTCmZvdXJfd2Vla190ZW1wcyA9IGdldF9wcmVkaWN0b3JzKGRhaWx5X3ZhbHVlcyA9IGRhaWx5X3RlbXBfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X3RlbXAgPSB0ZW1wX2RhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5fZGF5cyA9IDI4KQoKZm91cl93ZWVrX3Bsb3QgPSBmb3VyX3dlZWtfdGVtcHMgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKC1kYXRlKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAicGFyYW1ldGVyIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInRlbXAiKSAlPiUKICBmaWx0ZXIocGFyYW1ldGVyICVpbiUgYygidHdlbnR5LWVpZ2h0X2RheV9tZWFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAidHdlbnR5LWVpZ2h0X2RheV9tZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICJ0d2VudHktZWlnaHRfZGF5X21heCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgInR3ZW50eS1laWdodF9kYXlfbWluIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAidHdlbnR5LWVpZ2h0X2RheV92YXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICJ0d2VudHktZWlnaHRfZGF5X3JhbmdlIikpICU+JQogIG11dGF0ZShwYXJhbWV0ZXIgPSBwYXN0ZSh3b3JkKHBhcmFtZXRlciwgc3RhcnQgPSAzLCBzZXAgPSBmaXhlZCgiXyIpKSwgIl90ZW1wIiwgc2VwID0gIiIpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkYXRlLCB5ID0gdGVtcCwgY29sb3VyID0gcGFyYW1ldGVyKSkgKwogIGdlb21fbGluZShsaW5ld2lkdGggPSAxKSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKAogICAgIm1lYW5fdGVtcCIgPSAib2xpdmVkcmFiMyIsCiAgICAibWVkX3RlbXAiID0gInNlYWdyZWVuMyIsCiAgICAibWF4X3RlbXAiID0gInRvbWF0byIsCiAgICAibWluX3RlbXAiID0gImRvZGdlcmJsdWUiLAogICAgInJhbmdlX3RlbXAiID0gImdvbGRlbnJvZDMiLAogICAgInZhcl90ZW1wIiA9ICJkYXJrZ29sZGVucm9kMSIKICApKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGFzLkRhdGUoYygiMjAyMy0wMS0wMSIsICIyMDIzLTA0LTAxIiwgIjIwMjMtMDctMDEiKSkpICsKICBnZ3RpdGxlKCJGb3VyIFdlZWtzIikgKwogIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiAgICAgICB4ID0gIiIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAyMCkgKwogIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAyNzAsIGhqdXN0ID0gMCwgdmp1c3QgPSAwLjUpKQojIAojIAojICMjIyBFSUdIVCBXRUVLUwojIGVpZ2h0X3dlZWtfdGVtcHMgPSBnZXRfcHJlZGljdG9ycyhkYWlseV92YWx1ZXMgPSBkYWlseV90ZW1wX2RhdGEsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfdGVtcCA9IHRlbXBfZGF0YSwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5fZGF5cyA9IDU2KQojIAojIGVpZ2h0X3dlZWtfcGxvdCA9IGVpZ2h0X3dlZWtfdGVtcHMgJT4lIAojICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKC1kYXRlKSwKIyAgICAgICAgICAgICAgICBuYW1lc190byA9ICJwYXJhbWV0ZXIiLCAKIyAgICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidGVtcCIpICU+JSAKIyAgIGZpbHRlcihwYXJhbWV0ZXIgJWluJSBjKCJmaWZ0eS1zaXhfZGF5X21lYW4iLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgImZpZnR5LXNpeF9kYXlfbWVkIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICJmaWZ0eS1zaXhfZGF5X21heCIsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgImZpZnR5LXNpeF9kYXlfbWluIiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmlmdHktc2l4X2RheV92YXIiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgImZpZnR5LXNpeF9kYXlfcmFuZ2UiKSkgJT4lIAojICAgbXV0YXRlKHBhcmFtZXRlciA9IHBhc3RlKHdvcmQocGFyYW1ldGVyLCBzdGFydCA9IDMsIHNlcCA9IGZpeGVkKCJfIikpLCAiX3RlbXAiLCBzZXAgPSAiIikpICU+JSAKIyAgIGdncGxvdChhZXMoeCA9IGRhdGUsIHkgPSB0ZW1wLCBjb2xvdXIgPSBwYXJhbWV0ZXIpKSArIAojICAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDEpICsgCiMgICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoCiMgICAgICJtZWFuX3RlbXAiID0gIm9saXZlZHJhYjMiLAojICAgICAibWVkX3RlbXAiID0gInNlYWdyZWVuMyIsCiMgICAgICJtYXhfdGVtcCIgPSAidG9tYXRvIiwgIAojICAgICAibWluX3RlbXAiID0gImRvZGdlcmJsdWUiLAojICAgICAicmFuZ2VfdGVtcCIgPSAiZ29sZGVucm9kMyIsCiMgICAgICJ2YXJfdGVtcCIgPSAiZGFya2dvbGRlbnJvZDEiCiMgICApKSArIAojICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGFzLkRhdGUoYygiMjAyMy0wMS0wMSIsICIyMDIzLTA0LTAxIiwgIjIwMjMtMDctMDEiKSkpICsgCiMgICBnZ3RpdGxlKCJFaWdodCBXZWVrcyIpICsgCiMgICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAojICAgICAgICB4ID0gIiIpICsgCiMgICB0aGVtZV9idyhiYXNlX3NpemUgPSAyMCkgKyAKIyAgIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiMgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCiMgCmdnYXJyYW5nZShkYWlseV9wbG90LCB3ZWVrX3Bsb3QsIGZvdXJfd2Vla19wbG90LCAKICAgICAgICAgIGNvbW1vbi5sZWdlbmQgPSBULCBucm93ID0gMSwgbGVnZW5kID0gImJvdHRvbSIpCmBgYAoKVGhlIGRpZmZlcmVudCB0aW1lIHBlcmlvZHMgZXhhbWluZWQgYnkgdGhpcyBjbGltYXRlIGRhdGEgaGlnaGxpZ2h0cyB0aGF0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBtaW5pbXVtIGFuZCBtYXhpbXVtIHRlbXBlcmF0dXJlcyBjaGFuZ2VzIGJhc2VkIG9uIHRoZSB3aW5kb3cgZXhhbWluZWQuIEZvciBleGFtcGxlLCBtaW5pbXVtIGFuZCBtYXhpbXVtIHRlbXBlcmF0dXJlcyBleHBlcmllbmNlZCBvdmVyIHdlZWtseSBpbnRlcnZhbHMgYXJlIGNsb3NlbHkgbGlua2VkLCB3aGVyZWFzIHRoZXJlIGlzIGEgZGlzdGluY3Qgc2Vhc29uYWwgY3ljbGUgaW4gdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG1pbmltdW0gYW5kIG1heGltdW0gdGVtcGVyYXR1cmVzIGV4cGVyaWVuY2VkIG92ZXIgcGVyaW9kcyBvZiBmb3VyIHdlZWtzLiAKCmBgYHtyfQpvbmVfd2Vla19kb3lfZGF0YSA9IHdlZWtfdGVtcHMgJT4lIAogIG11dGF0ZShkb3kgPSB5ZGF5KGRhdGUpKQoKb25lX3dlZWtfdGVtcF9jaXJjbGUgPSBnZ3Bsb3Qob25lX3dlZWtfZG95X2RhdGEsIGFlcyh4ID0gc2V2ZW5fZGF5X21lYW5fbWF4LCB5ID0gc2V2ZW5fZGF5X21lYW5fbWluLCBjb2xvdXIgPSBkb3kpKSArIAogIGdlb21fcG9pbnQoKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudDIoCiAgICBoaWdoID0gImRvZGdlcmJsdWU0IiwKICAgIG1pZCA9ICJjb3JhbDIiLAogICAgbG93ID0gImRvZGdlcmJsdWU0IiwKICAgICAgbWlkcG9pbnQgPSAxODIuNSkgKyAKICBsYWJzKHggPSAiTWF4LiBUZW1wLiAowrBDKSIsCiAgICAgICB5ID0gIk1pbi4gVGVtcC4gKMKwQykiKSArIAogIGxhYnMoeCA9ICJNYXguIFRlbXAuICjCsEMpIiwKICAgICAgIHkgPSAiTWluLiBUZW1wLiAowrBDKSIpICsgCiAgZ2d0aXRsZSgiT25lIFdlZWsiKSArIAogIHRoZW1lX21hdHQoKQoKZm91cl93ZWVrX2RveV9kYXRhID0gZm91cl93ZWVrX3RlbXBzICU+JSAKICBtdXRhdGUoZG95ID0geWRheShkYXRlKSkKCmZvdXJfd2Vla190ZW1wX2NpcmNsZSA9IGdncGxvdChmb3VyX3dlZWtfZG95X2RhdGEsIGFlcyh4ID0gYHR3ZW50eS1laWdodF9kYXlfbWF4YCwgeSA9IGB0d2VudHktZWlnaHRfZGF5X21pbmAsIGNvbG91ciA9IGRveSkpICsgCiAgZ2VvbV9wb2ludCgpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50MigKICAgIGhpZ2ggPSAiZG9kZ2VyYmx1ZTQiLAogICAgbWlkID0gImNvcmFsMiIsCiAgICBsb3cgPSAiZG9kZ2VyYmx1ZTQiLAogICAgICBtaWRwb2ludCA9IDE4Mi41KSArIAogIGxhYnMoeCA9ICJNYXguIFRlbXAuICjCsEMpIiwKICAgICAgIHkgPSAiTWluLiBUZW1wLiAowrBDKSIpICsgCiAgZ2d0aXRsZSgiRm91ciBXZWVrIikgKyAKICB0aGVtZV9tYXR0KCkKCmdnYXJyYW5nZShvbmVfd2Vla190ZW1wX2NpcmNsZSwgZm91cl93ZWVrX3RlbXBfY2lyY2xlLAogICAgICAgICAgY29tbW9uLmxlZ2VuZCA9IFQsIGxlZ2VuZCA9ICJib3R0b20iKQpgYGAKClRoZSB0aGVybWFsIGVudmlyb25tZW50IG92ZXIgYW55IHBlcmlvZCBvZiB0aW1lIG1heSBkcml2ZSBwYXR0ZXJucyBpbiB0aGVybWFsIGFjY2xpbWF0aW9uLiBUbyBleHBsb3JlIHRoZSBwb3RlbnRpYWwgZWZmZWN0cyBvZiBkaWZmZXJlbnQgYWNjbGltYXRpb24gd2luZG93cywgd2UgZXhhbWluZWQgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlcm1hbCBsaW1pdHMgYW5kIGRpZmZlcmVudCByZXByZXNlbnRhdGlvbnMgb2YgdGhlIHRoZXJtYWwgZW52aXJvbm1lbnQgZm9yIGRpZmZlcmVudCBwZXJpb2RzIG9mIHRpbWUuIFNob3duIGJlbG93IGFyZSB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnRzIGZvciB0aGVzZSByZWxhdGlvbnNoaXBzLiBFYWNoIGZhY2V0IHNob3dzIHRoZSByZWxhdGlvbnNoaXAgZm9yIGEgZGlmZmVyZW50IGRpbWVuc2lvbiBvZiB0aGUgdGhlcm1hbCBlbnZpcm9ubWVudC4gQ29ycmVsYXRpb24gY29lZmZpY2llbnRzIGFyZSBwbG90dGVkIGZvciBkaWZmZXJlbnQgZHVyYXRpb25zLCBmb3Igc3BlY2llcyB0aGF0IHdlcmUgY29sbGVjdGVkIG1vcmUgdGhhbiBmaXZlIHRpbWVzLiBPbmx5IGRhdGEgZm9yIG1hdHVyZSBmZW1hbGUgY29wZXBvZHMgd2FzIGluY2x1ZGVkLiAKCldlIGNhbiBzZWUgdGhhdCwgaW4gZ2VuZXJhbCwgY29wZXBvZHMgYXJlIHJlc3BvbmRpbmcgdG8gcHJveGltYXRlIGN1ZXMgZnJvbSB0aGUgdGhlcm1hbCBlbnZpcm9ubWVudCwgd2l0aCBjb3JyZWxhdGlvbnMgZ2VuZXJhbGx5IGRyb3BwaW5nIG9mZiBzdWJzdGFudGlhbGx5IGFzIGFjY2xpbWF0aW9uIHdpbmRvdyBkdXJhdGlvbiBpbmNyZWFzZXMuIEFuIGV4Y2VwdGlvbiBpcyAqRXBpc2NodXJhIGxhY3VzdHJpcyosIHdoaWNoIGFwcGVhcnMgdG8gYmUgcmVzcG9uZGluZyB0byBtYXhpbXVtIHRlbXBlcmF0dXJlcyBleHBlcmllbmNlZCBvdmVyIGEgMjAgZGF5IHRpbWUgcGVyaW9kLiAKCmBgYHtyfQojIyMgUHVsbGluZyBwcmVkaWN0b3JzIGFuZCBtZWFzdXJpbmcgY29ycmVsYXRpb25zIGZvciBtdWNoIGZpbmVyIHRpbWVzY2FsZXM7IDEtNTYgZGF5cwoKd29yZHNfdG9fbnVtYmVycyA8LSBmdW5jdGlvbihzKSB7CiAgcyA8LSBzdHJpbmdyOjpzdHJfdG9fbG93ZXIocykKICBmb3IgKGkgaW4gMDo1NikKICAgIHMgPC0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKHMsIHdvcmRzKGkpLCBhcy5jaGFyYWN0ZXIoaSkpCiAgcwp9CgpudW1fY29sbHMgPSBmdWxsX2RhdGEgJT4lIAogIGZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICBzZWxlY3QoY29sbGVjdGlvbl9kYXRlLCBzcF9uYW1lKSAlPiUgIAogIGRpc3RpbmN0KCkgJT4lICAKICBjb3VudChzcF9uYW1lKSAlPiUgCiAgZmlsdGVyKG4gPj0gNSkKCmNvcnJfdmFscyA9IGRhdGEuZnJhbWUoKQoKZHVyX3ZhbHMgPSBjKDIsIDMsIDQsIDUsIDEwLCAxNSwgMjAsIDI1LCAzMCkKZm9yKGkgaW4gZHVyX3ZhbHMpewogIAogIGR1cmF0aW9uX3RlbXBzID0gZ2V0X3ByZWRpY3RvcnMoZGFpbHlfdmFsdWVzID0gZGFpbHlfdGVtcF9kYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfdGVtcCA9IHRlbXBfZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbl9kYXlzID0gaSkgJT4lIAogICAgZmlsdGVyKGRhdGUgJWluJSBhc19kYXRlKHVuaXF1ZShmdWxsX2RhdGEkY29sbGVjdGlvbl9kYXRlKSkpCiAgCiAgY29ycl9kYXRhID0gZnVsbF9kYXRhICU+JQogICAgZmlsdGVyKHNwX25hbWUgJWluJSBudW1fY29sbHMkc3BfbmFtZSkgJT4lIAogICAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAogICAgbXV0YXRlKGNvbGxlY3Rpb25fZGF0ZSA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSkgJT4lIAogICAgaW5uZXJfam9pbihkdXJhdGlvbl90ZW1wcywgam9pbl9ieShjb2xsZWN0aW9uX2RhdGUgPT0gZGF0ZSkpICU+JSAKICAgIHBpdm90X2xvbmdlcihjb2xzID0gYyhjb2xsZWN0aW9uX3RlbXAsIGNvbnRhaW5zKCJkYXlfIikpLAogICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ2YWx1ZSIsIAogICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInByZWRpY3RvciIpICU+JSAgCiAgICBncm91cF9ieShzcF9uYW1lLCBwcmVkaWN0b3IpICU+JSAKICAgIHN1bW1hcmlzZShjb3JyZWxhdGlvbiA9IGNvci50ZXN0KGN0bWF4LCB2YWx1ZSkkZXN0aW1hdGUsCiAgICAgICAgICAgICAgcC52YWx1ZSA9IGNvci50ZXN0KGN0bWF4LCB2YWx1ZSkkcC52YWx1ZSwKICAgICAgICAgICAgICBjaV9sb3cgPSBjb3IudGVzdChjdG1heCwgdmFsdWUpJGNvbmYuaW50WzFdLAogICAgICAgICAgICAgIGNpX2hpZ2ggPSBjb3IudGVzdChjdG1heCwgdmFsdWUpJGNvbmYuaW50WzJdKSAlPiUgCiAgICBmaWx0ZXIocHJlZGljdG9yICE9ICJjb2xsZWN0aW9uX3RlbXAiKSAlPiUgCiAgICBtdXRhdGUoc2lnID0gaWZlbHNlKHAudmFsdWUgPDAuMDUsICJTaWcuIiwgIk5vbiBTaWcuIikpICU+JSAKICAgIHNlcGFyYXRlKHByZWRpY3RvciwgIl9kYXlfIiwgaW50byA9IGMoTkEsICJwYXJhbWV0ZXIiKSkgJT4lIAogICAgbXV0YXRlKGR1cmF0aW9uID0gaSkKICAKICBjb3JyX3ZhbHMgPSBiaW5kX3Jvd3MoY29ycl92YWxzLCBjb3JyX2RhdGEpCn0KCmNvcnJfdmFscyA9IGNvcnJfdmFscyAlPiUgIAogIG11dGF0ZShkdXJhdGlvbiA9IGFzLm51bWVyaWMoZHVyYXRpb24pKQpgYGAKCmBgYHtyIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02fQpjb3JyX3ZhbHMgJT4lIAptdXRhdGUocGFyYW1ldGVyID0gZmN0X3JlbGV2ZWwocGFyYW1ldGVyLCBjKCJtaW4iLCAibWF4IiwgInJhbmdlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibWVhbiIsICJtZWQiLCAidmFyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibWVhbl9taW4iLCAibWVhbl9tYXgiLCAibWVhbl9yYW5nZSIpKSkgJT4lIApnZ3Bsb3QoYWVzKHggPSBkdXJhdGlvbiwgeSA9IGNvcnJlbGF0aW9uLCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBmYWNldF93cmFwKC5+cGFyYW1ldGVyKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDEpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgbGFicyh4ID0gIkR1cmF0aW9uIChkYXlzKSIsCiAgICAgICB5ID0gIkNvcnJlbGF0aW9uIiwgCiAgICAgICBjb2xvdXIgPSAiU3BlY2llcyIpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoKQpgYGAKClNob3duIGhlcmUgYXJlIHRoZSB0b3AgdGhyZWUgZmFjdG9ycyBmb3IgZWFjaCBzcGVjaWVzLiAKCmBgYHtyIHByZWRpY3Rvci1jb3JyZWxhdGlvbnN9CiMgCiMgY29ycl92YWxzID0gZnVsbF9kYXRhICU+JQojICAgZmlsdGVyKHNwX25hbWUgJWluJSBudW1fY29sbHMkc3BfbmFtZSkgJT4lIAojICAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAojICAgbXV0YXRlKGNvbGxlY3Rpb25fZGF0ZSA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSkgJT4lIAojICAgZnVsbF9qb2luKHRlbXBfcHJlZGljdG9ycywgam9pbl9ieShjb2xsZWN0aW9uX2RhdGUgPT0gZGF0ZSkpICU+JSAKIyAgIHBpdm90X2xvbmdlcihjb2xzID0gYyhjb2xsZWN0aW9uX3RlbXAsIG1lYW5fdGVtcDp0YWlsKG5hbWVzKC4pLCAxKSksCiMgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInZhbHVlIiwgCiMgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAicHJlZGljdG9yIikgJT4lICAKIyAgIGdyb3VwX2J5KHNwX25hbWUsIHByZWRpY3RvcikgJT4lIAojICAgc3VtbWFyaXNlKGNvcnJlbGF0aW9uID0gY29yLnRlc3QoY3RtYXgsIHZhbHVlKSRlc3RpbWF0ZSwKIyAgICAgICAgICAgICBwLnZhbHVlID0gY29yLnRlc3QoY3RtYXgsIHZhbHVlKSRwLnZhbHVlLAojICAgICAgICAgICAgIGNpX2xvdyA9IGNvci50ZXN0KGN0bWF4LCB2YWx1ZSkkY29uZi5pbnRbMV0sCiMgICAgICAgICAgICAgY2lfaGlnaCA9IGNvci50ZXN0KGN0bWF4LCB2YWx1ZSkkY29uZi5pbnRbMl0pICU+JSAKIyAgIG11dGF0ZShzaWcgPSBpZmVsc2UocC52YWx1ZSA8MC4wNSwgIlNpZy4iLCAiTm9uIFNpZy4iKSkKCmNvcnJfdmFscyAlPiUgIAogIGZpbHRlcihzaWcgPT0gIlNpZy4iKSAlPiUgCiAgZHJvcF9uYShjb3JyZWxhdGlvbikgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUpICU+JQogIGFycmFuZ2UoZGVzYyhjb3JyZWxhdGlvbikpICU+JSAKICBzbGljZV9oZWFkKG4gPSAzKSAlPiUgCiAgc2VsZWN0KCJTcGVjaWVzIiA9IHNwX25hbWUsICJQcmVkaWN0b3IiID0gcGFyYW1ldGVyLCAiRHVyYXRpb24iID0gZHVyYXRpb24sICJDb3JyZWxhdGlvbiIgPSBjb3JyZWxhdGlvbiwgIlAtVmFsdWUiID0gcC52YWx1ZSkgJT4lIAogIGtuaXRyOjprYWJsZShhbGlnbiA9ICJjIikKYGBgCgojIyBUcmFpdCBWYXJpYXRpb24gCmBgYHtyIGN0bWF4LWFuZC1zaXplLXN1bS1wbG90LCBmaWcud2lkdGg9MjAsIGZpZy5oZWlnaHQ9NX0KIyBjdG1heF9wbG90ID0gZnVsbF9kYXRhICU+JSAKIyAgIG11dGF0ZSggI3NwX25hbWUgPSBzdHJfcmVwbGFjZShzcF9uYW1lLCBwYXR0ZXJuID0gIiAiLAojICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGFjZW1lbnQgPSAiXG4iKSwKIyAgICAgc3BfbmFtZSA9IGZjdF9yZW9yZGVyKHNwX25hbWUsIGN0bWF4LCBtZWFuKSkgJT4lIAojICAgZ2dwbG90KGFlcyh5ID0gc3BfbmFtZSwgeCA9IGN0bWF4KSkgKyAKIyAgIGdlb21fcG9pbnQoYWVzKGNvbG91cj0gc3BfbmFtZV9zdWIpLAojICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC4zKSwKIyAgICAgICAgICAgICAgc2l6ZSA9IDQpICsgCiMgICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKIyAgIHhsYWIoTlVMTCkgKyAKIyAgIGxhYnMoeSA9ICIiLAojICAgICAgICB4ID0gIkNUbWF4ICjCsEMpIiwKIyAgICAgICAgY29sb3VyID0gIkdyb3VwIikgKyAKIyAgIHRoZW1lX21hdHQoKSArIAojICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQojIAojIHNpemVfcGxvdCA9IGZ1bGxfZGF0YSAlPiUgCiMgICBtdXRhdGUoc3BfbmFtZSA9IGZjdF9yZW9yZGVyKHNwX25hbWUsIGN0bWF4LCBtZWFuKSkgJT4lIAojICAgZ2dwbG90KGFlcyh5ID0gc3BfbmFtZSwgeCA9IHNpemUpKSArIAojICAgZ2VvbV9wb2ludChhZXMoY29sb3VyPSBzcF9uYW1lX3N1YiksCiMgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjMpLAojICAgICAgICAgICAgICBzaXplID0gNCkgKyAKIyAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAojICAgbGFicyh4ID0gIlByb3NvbWUgTGVuZ3RoIChtbSkiLAojICAgICAgICB5ID0gIiIsIAojICAgICAgICBjb2xvdXIgPSAiR3JvdXAiKSArIAojICAgZ3VpZGVzKGNvbG9yID0gZ3VpZGVfbGVnZW5kKG5jb2wgPSAxKSkgKwojICAgdGhlbWVfbWF0dChiYXNlX3NpemUgPSApICsgCiMgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAojICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiMgICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwLCJjbSIpKQojIAojIHRyYWl0X3Bsb3QgPSBjdG1heF9wbG90ICsgc2l6ZV9wbG90CiMgdHJhaXRfcGxvdApgYGAKClNob3duIGJlbG93IGFyZSB0aGUgZGlzdHJpYnV0aW9ucyBvZiB0aGVybWFsIGxpbWl0cyBmb3IgZWFjaCBzcGVjaWVzLiBUaGlzIGluY2x1ZGVzIGFsbCBkYXRhIChhbGwgY29sbGVjdGlvbnMsIHN0YWdlcywgc2V4ZXMsIGV0Yy4pLiBJdCdzIGNsZWFyIHRoYXQgdGhlcmUgaXMgc3Vic3RhbnRpYWwgdmFyaWF0aW9uIGluIHRoZXJtYWwgbGltaXRzIGZvciBzZXZlcmFsIHNwZWNpZXMuIAoKYGBge3IgY3RtYXgtYW5kLXNpemUtaGlzdG9ncmFtcywgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9MjEsIGluY2x1ZGUgPSBGfQpmdWxsX2RhdGEgJT4lIAptdXRhdGUoc3BfbmFtZSA9IGZjdF9yZW9yZGVyKHNwX25hbWUsIGN0bWF4LCBtZWFuKSkgJT4lIApnZ3Bsb3QoYWVzKHggPSBjdG1heCwgZmlsbCA9IHNwX25hbWUpKSArIAogIGZhY2V0X3dyYXAoLn5zcF9uYW1lLCBuY29sID0gMSkgKyAKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIGxhYnMoeCA9ICJDVG1heCAowrBDKSIpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyZXk5NSIpKQpgYGAKClNob3duIGJlbG93IGFyZSB0aGUgY2x1dGNoIHNpemUgZGlzdHJpYnV0aW9ucyBmb3IgdGhlIHRocmVlIGRpYXB0b21paWQgc3BlY2llcywgd2hpY2ggcHJvZHVjZSBlZ2cgc2FjcyB0aGF0IGFsbG93IGZvciBlYXN5IHF1YW50aWZpY2F0aW9uIG9mIGZlY3VuZGl0eS4gCgpgYGB7ciBmZWN1bmRpdHktaGlzdG9ncmFtLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD0xMH0KZnVsbF9kYXRhICU+JSAgCiAgZHJvcF9uYShmZWN1bmRpdHkpICU+JSAgCiAgZ2dwbG90KGFlcyh4ID0gZmVjdW5kaXR5LCBmaWxsID0gc3BfbmFtZV9zdWIpKSArIAogIGZhY2V0X3dyYXAoLn5zcF9uYW1lX3N1YiwgbmNvbCA9IDEpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAyKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICBsYWJzKHggPSAiRmVjdW5kaXR5ICgjIEVnZ3MpIikgKwogIHRoZW1lX21hdHRfZmFjZXRzKCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKT25lIG9mIHRoZSBtYWluIGFpbXMgb2YgdGhpcyBwcm9qZWN0IGlzIHRvIGV4YW1pbmUgdGhlIHBhdHRlcm5zIGFuZCBwcm9jZXNzZXMgZHJpdmluZyB2YXJpYXRpb24gaW4gdXBwZXIgdGhlcm1hbCBsaW1pdHMgYWNyb3NzIHRoZXNlIHNwZWNpZXMgb2YgY29wZXBvZHMuIAoKIyMjIFZhcmlhdGlvbiB3aXRoIHRlbXBlcmF0dXJlIAoKV2UgZXhwZWN0IG9uZSBvZiB0aGUgcHJpbWFyeSBkcml2ZXJzIG9mIGNvcGVwb2QgdGhlcm1hbCBsaW1pdHMgdG8gYmUgdGVtcGVyYXR1cmUuIFRoZSBjb3JyZWxhdGlvbiBhbmFseXNpcyBoYXMgc2hvd24gdGhhdCB0aGUgY29wZXBvZHMgYXJlIGdlbmVyYWxseSAoYWx0aG91Z2ggbm90IGFsd2F5cykgcmVzcG9uZGluZyB0byB0aGUgcmVjZW50IHRoZXJtYWwgZW52aXJvbm1lbnQuIFNob3duIGJlbG93IGFyZSB0aGVybWFsIGxpbWl0cywgYm9keSBzaXplLCBhbmQgZmVjdW5kaXR5IHZhbHVlcyBwbG90dGVkIGFnYWluc3QgdGhlIHRlbXBlcmF0dXJlIGF0IHRoZSB0aW1lIG9mIGNvbGxlY3Rpb24uIEFsc28gc2hvd24gaXMgd2FybWluZyB0b2xlcmFuY2UsIGNhbGN1bGF0ZWQgYXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB1cHBlciB0aGVybWFsIGxpbWl0IGFuZCB0aGUgY29sbGVjdGlvbiB0ZW1wZXJhdHVyZS4gCgpXZSBnZW5lcmFsbHkgc2VlIGFuIGluY3JlYXNlIGluIHRoZXJtYWwgbGltaXRzIHdpdGggaW5jcmVhc2luZyBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlLCBhIHNsaWdodCBkZWNyZWFzZSBpbiBib2R5IHNpemUsIGFuZCB2YXJpYWJsZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gdGVtcGVyYXR1cmUgYW5kIGZlY3VuZGl0eS4gQWxsIHNwZWNpZXMgbWFpbnRhaW5lZCBzb21lIGRlZ3JlZSBvZiBidWZmZXIgYmV0d2VlbiBlbnZpcm9ubWVudGFsIHRlbXBlcmF0dXJlcyBhbmQgdXBwZXIgdGhlcm1hbCBsaW1pdHMsIGJ1dCAqRXBpc2NodXJhKiBhbmQgKkwuIG1pbnV0dXMqIGFwcHJvYWNoZWQgdGhlaXIgdXBwZXIgdGhlcm1hbCBsaW1pdHMgZHVyaW5nIHRoZSB3YXJtZXN0IGNvbGxlY3Rpb25zIGR1cmluZyB0aGUgc3VtbWVyLiAKCmBgYHtyIHRyYWl0LWNvbGwtdGVtcC1wbG90cywgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTEwfQpjdG1heF90ZW1wID0gZ2dwbG90KGZ1bGxfZGF0YSwgYWVzKHggPSBjb2xsZWN0aW9uX3RlbXAsIHkgPSBjdG1heCwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgbGluZXdpZHRoID0gMykgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsgCiAgbGFicyh4ID0gIkNvbGxlY3Rpb24gVGVtcGVyYXR1cmUgKMKwQykiLCAKICAgICAgIHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgpzaXplX3RlbXAgPSBnZ3Bsb3QoZmlsdGVyKGZ1bGxfZGF0YSwgc2V4ICE9ICJqdXZlbmlsZSIpLCBhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IHNpemUsIGNvbG91ciA9IHNwX25hbWUpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGxpbmV3aWR0aCA9IDMpICsKICBnZW9tX3BvaW50KHNpemUgPSAzKSArIAogIGxhYnMoeCA9ICJDb2xsZWN0aW9uIFRlbXBlcmF0dXJlICjCsEMpIiwgCiAgICAgICB5ID0gIkxlbmd0aCAobW0pIiwKICAgICAgIGNvbG91ciA9ICJTcGVjaWVzIikgICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCnd0X3RlbXAgPSBnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IHdhcm1pbmdfdG9sLCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBsaW5ld2lkdGggPSAzKSArCiAgZ2VvbV9wb2ludChzaXplID0gMykgKyAKICBsYWJzKHggPSAiQ29sbGVjdGlvbiBUZW1wZXJhdHVyZSAowrBDKSIsIAogICAgICAgeSA9ICJXYXJtaW5nIFRvbGVyYW5jZSAowrBDKSIsCiAgICAgICBjb2xvdXIgPSAiU3BlY2llcyIpICArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgplZ2dzX3RlbXAgPSBnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IGZlY3VuZGl0eSwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgbGluZXdpZHRoID0gMykgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsgCiAgbGFicyh4ID0gIkNvbGxlY3Rpb24gVGVtcGVyYXR1cmUgKMKwQykiLCAKICAgICAgIHkgPSAiRmVjdW5kaXR5ICgjIEVnZ3MpIiwKICAgICAgIGNvbG91ciA9ICJTcGVjaWVzIikgICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCmdnYXJyYW5nZShjdG1heF90ZW1wLCBzaXplX3RlbXAsIHd0X3RlbXAsIGVnZ3NfdGVtcCwgCiAgICAgICAgICBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gInJpZ2h0IikKYGBgCgpgYGB7ciBmaWcud2lkdGg9NywgZmlnLmhlaWdodD01fQpmdWxsX2RhdGEgJT4lIAogICNmaWx0ZXIoc2V4ID09ICJmZW1hbGUiKSAlPiUgIAogIGdyb3VwX2J5KHNwX25hbWUpICU+JSBmaWx0ZXIobigpID4gNSkgJT4lIGZpbHRlcighc3RyX2RldGVjdChzcF9uYW1lLCBwYXR0ZXJuID0gImtpbmR0aSIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gY3RtYXgsIGNvbG91ciA9IHNwX25hbWUpKSArIAogIGZhY2V0X3dyYXAoc3BfbmFtZX4uKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDIsIGFscGhhID0gMC44KSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwgbGluZXdpZHRoID0gMikgKyAKICBsYWJzKHggPSAiQ29sbGVjdGlvbiBUZW1wLiAowrBDKSIsIAogICAgICAgeSA9ICJDVG1heCAowrBDKSIpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKCgpgYGB7ciBjdG1heC1jb2xsLXRlbXAtbW9kZWwsIGluY2x1ZGUgPSBGfQojIGFkdWx0X2RhdGEgPSBmdWxsX2RhdGEgJT4lIAojICAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIikKbW9kZWxfZGF0YSA9IGZ1bGxfZGF0YSAlPiUgIAogIGRyb3BfbmEoc2l6ZSwgY3RtYXgpCgpjdG1heF90ZW1wLm1vZGVsID0gbG0oZGF0YSA9IG1vZGVsX2RhdGEsIGN0bWF4IH4gY29sbGVjdGlvbl90ZW1wICogc3BfbmFtZSArIHNleCkKc2l6ZV90ZW1wLm1vZGVsID0gbG0oZGF0YSA9IG1vZGVsX2RhdGEsIHNpemUgfiBjb2xsZWN0aW9uX3RlbXAgKiBzcF9uYW1lICsgc2V4KQoKa25pdHI6OmthYmxlKGNhcjo6QW5vdmEoY3RtYXhfdGVtcC5tb2RlbCkpCgpjdG1heF9yZXNpZHMgPSBjYmluZChtb2RlbF9kYXRhLCAicmVzaWRzIiA9IGN0bWF4X3RlbXAubW9kZWwkcmVzaWR1YWxzLCAic2l6ZV9yZXNpZHMiID0gc2l6ZV90ZW1wLm1vZGVsJHJlc2lkdWFscykKCmBgYAoKQ29wZXBvZHMgc3BlbnQgc2V2ZXJhbCBkYXlzIGluIGxhYiBkdXJpbmcgZXhwZXJpbWVudHMuIFNob3duIGJlbG93IGFyZSB0aGUgQ1RtYXggcmVzaWR1YWxzICh0YWtlbiBmcm9tIGEgbW9kZWwgb2YgQ1RtYXggYWdhaW5zdCBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlKSBwbG90dGVkIGFnYWluc3QgdGhlIHRpbWUgc3BlbnQgaW4gbGFiIGJlZm9yZSBtZWFzdXJlbWVudHMgd2VyZSBtYWRlLiBXZSBjYW4gc2VlIGNsZWFybHkgdGhhdCB0aGVybWFsIGxpbWl0cyBhcmUgZmFpcmx5IHN0YWJsZSBvdmVyIHRpbWUuIAoKYGBge3IgY3RtYXgtdGltZS1pbi1sYWIsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD0xMH0KZ2dwbG90KGN0bWF4X3Jlc2lkcywgYWVzKHggPSBkYXlzX2luX2xhYiwgeSA9IHJlc2lkcywgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfd3JhcChzcF9uYW1lfi4pICsgCiAgZ2VvbV9wb2ludChzaXplID0gNCwgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGLCBsaW5ld2lkdGggPSAyKSArIAogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDA6NSkpICsgCiAgbGFicyh4ID0gIkRheXMgaW4gbGFiIiwgCiAgICAgICB5ID0gIkNUbWF4IFJlc2lkdWFscyIpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgpUaGUgdGVybSAiYWNjbGltYXRpb24gcmVzcG9uc2UgcmF0aW8iIGlzIG9mdGVuIHVzZWQgdG8gZGVzY3JpYmUgdGhlIGVmZmVjdCBvZiB0ZW1wZXJhdHVyZSBvbiB0aGVybWFsIGxpbWl0cy4gVGhlIEFSUiBpcyBjYWxjdWxhdGVkIGFzIHRoZSBjaGFuZ2UgaW4gdGhlcm1hbCBsaW1pdHMgcGVyIGRlZ3JlZSBjaGFuZ2UgaW4gYWNjbGltYXRpb24gdGVtcGVyYXR1cmUuIEZvciBvdXIgZGF0YSwgd2Ugd2lsbCBlc3RpbWF0ZSBBUlIgYXMgdGhlIHNsb3BlIG9mIENUbWF4IGFnYWluc3QgY29sbGVjdGlvbiB0ZW1wZXJhdHVyZS4gCgpgYGB7cn0KY29lZl9tb2RlbF9kYXRhID0gZnVsbF9kYXRhICU+JSAKICBncm91cF9ieShzcF9uYW1lLCBzZXgpICU+JSAKICBmaWx0ZXIobigpID4gNSAmICFzdHJfZGV0ZWN0KHNwX25hbWUsIHBhdHRlcm4gPSAia2luZHRpIikpIAoKY29lZl9uID0gZnVsbF9kYXRhICU+JSAKICBncm91cF9ieShzcF9uYW1lLCBzZXgpICU+JSAKICBmaWx0ZXIobigpID4gNSkgJT4lIAogIHN1bW1hcmlzZShzYW1wbGVfbiA9IG4oKSwgCiAgICAgICAgICAgIG1lYW5fY3RtYXggPSBtZWFuKGN0bWF4KSkKCkFSUl92YWxzID0gY29lZl9tb2RlbF9kYXRhICU+JSAKICBkbyhicm9vbTo6dGlkeShsbShjdG1heCB+IGNvbGxlY3Rpb25fdGVtcCwgZGF0YSA9IC4pKSkgJT4lIAogIGZpbHRlcih0ZXJtICE9ICIoSW50ZXJjZXB0KSIpICU+JSAKICBzZWxlY3Qoc3BfbmFtZSwgc2V4LCAiQVJSIiA9IGVzdGltYXRlLCBzdGQuZXJyb3IpICU+JSAKICBhcnJhbmdlKEFSUikgJT4lIAogIGlubmVyX2pvaW4oY29lZl9uLCBieSA9IGMoInNwX25hbWUiLCAic2V4IikpCiAgCkFSUl92YWxzICU+JSAKICBzZWxlY3QoIlNwZWNpZXMiID0gc3BfbmFtZSwgCiAgICAgICAgICJHcm91cCIgPSBzZXgsIAogICAgICAgICAiTiIgPSBzYW1wbGVfbiwKICAgICAgICAgQVJSLCAKICAgICAgICAgIkVycm9yIiA9IHN0ZC5lcnJvcikgJT4lIAogIGtuaXRyOjprYWJsZSgpCmBgYAoKYGBge3IgY29lZi1zdW1tYXJ5LCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NX0KY29lZl9wbG90ID0gQVJSX3ZhbHMgJT4lIAogIG11dGF0ZSgiYWJiciIgPSBjYXNlX3doZW4oCiAgICBzcF9uYW1lID09ICJFcGlzY2h1cmEgbGFjdXN0cmlzIiB+ICJFLiBsYWMiLAogICAgc3BfbmFtZSA9PSAiTGVwdG9kaWFwdG9tdXMgbWludXR1cyIgfiAiTC4gbWluIiwgCiAgICBzcF9uYW1lID09ICJTa2lzdG9kaWFwdG9tdXMgb3JlZ29uZW5zaXMiIH4gIlMuIG9yZSIsCiAgICBzcF9uYW1lID09ICJMZXB0b2RpYXB0b211cyBzaWNpbGlzIiB+ICJMLiBzaWMiCiAgKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGFiYnIsIHkgPSBBUlIsIGNvbG91ciA9IHNwX25hbWUsIHNoYXBlID0gc2V4KSkgKyAKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gQVJSIC0gc3RkLmVycm9yLCB5bWF4ID0gQVJSICsgc3RkLmVycm9yKSwKICAgICAgICAgICAgICAgIHdpZHRoID0gMC4zNSwgbGluZXdpZHRoID0gMSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNSkpICsgCiAgZ2VvbV9wb2ludChzaXplID0gNSwKICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjUpKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIGd1aWRlcyhjb2xvdXIgPSAibm9uZSIpICsgCiAgbGFicyh4ID0gIlNwZWNpZXMiLCAKICAgICAgIHkgPSAiQVJSIiwgCiAgICAgICBzaGFwZSA9ICJHcm91cCIpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCmNvZWZfbGltX3Bsb3QgPSBnZ3Bsb3QoQVJSX3ZhbHMsIGFlcyh4ID0gbWVhbl9jdG1heCwgeSA9IEFSUikpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3VyID0gImdyZXk3MCIsIHNlID0gRiwgbGluZXdpZHRoID0gMikgKyAKICBnZW9tX2Vycm9yYmFyKGFlcyhjb2xvdXIgPSBzcF9uYW1lLCB5bWluID0gQVJSIC0gc3RkLmVycm9yLCB5bWF4ID0gQVJSICsgc3RkLmVycm9yKSwKICAgICAgICAgICAgICAgIHdpZHRoID0gMC41LCBsaW5ld2lkdGggPSAxLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC41KSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBzcF9uYW1lLCBzaGFwZSA9IHNleCApLAogICAgICAgICAgICAgc2l6ZSA9IDUsCiAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC41KSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIGd1aWRlcyhjb2xvdXIgPSAibm9uZSIpICsgCiAgbGFicyh4ID0gIk1lYW4gQ1RtYXggKMKwQykiLCAKICAgICAgIHkgPSAiQVJSIiwgCiAgICAgICBzaGFwZSA9ICJHcm91cCIpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCmdnYXJyYW5nZShjb2VmX3Bsb3QsIGNvZWZfbGltX3Bsb3QsIGNvbW1vbi5sZWdlbmQgPSBULCBsZWdlbmQgPSAicmlnaHQiKQpgYGAKCiMjIyBTZXggYW5kIHN0YWdlIHZhcmlhdGlvbiBpbiB0aGVybWFsIGxpbWl0cyAKUHJldmlvdXMgc2VjdGlvbnMgaGF2ZSBnZW5lcmFsbHkgbHVtcGVkIGp1dmVuaWxlLCBmZW1hbGUsIGFuZCBtYWxlIGluZGl2aWR1YWxzIHRvZ2V0aGVyLiBUaGVyZSBtYXkgYmUgaW1wb3J0YW50IHN0YWdlLSBvciBzZXgtc3BlY2lmaWMgZGlmZmVyZW5jZXMgaW4gQ1RtYXggdGhvdWdoLiBGb3Igc2V2ZXJhbCBzcGVjaWVzLCB3ZSBoYXZlIG1lYXN1cmVtZW50cyBmb3IgaW5kaXZpZHVhbHMgaW4gZGlmZmVyZW50IHN0YWdlcyBvciBvZiBkaWZmZXJlbnQgc2V4ZXMuIAoKYGBge3Igc2V4LXN0YWdlLXRhYmxlfQpzZXhfc2FtcGxlX3NpemVzID0gY3RtYXhfcmVzaWRzICU+JSAgCiAgZ3JvdXBfYnkoc3BfbmFtZSwgc2V4KSAlPiUgIAogIHN1bW1hcmlzZShudW0gPSBuKCkpICU+JSAgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IHNwX25hbWUsCiAgICAgICAgICAgICAgbmFtZXNfZnJvbSA9IHNleCwgCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBudW0sCiAgICAgICAgICAgICAgdmFsdWVzX2ZpbGwgPSAwKSAlPiUgCiAgc2VsZWN0KCJTcGVjaWVzIiA9IHNwX25hbWUsICJKdXZlbmlsZSIgPSBqdXZlbmlsZSwgIkZlbWFsZSIgPSBmZW1hbGUsICJNYWxlIiA9IG1hbGUpCgprbml0cjo6a2FibGUoc2V4X3NhbXBsZV9zaXplcywgYWxpZ24gPSAiYyIpCmBgYAoKVGhlIGZlbWFsZS1tYWxlIGFuZCBmZW1hbGUtanV2ZW5pbGUgY29tcGFyaXNvbnMgc2hvdyB0aGF0IHRoZXJlIGFyZSBnZW5lcmFsbHkgbm8gZGlmZmVyZW5jZXMgaW4gdGhlcm1hbCBsaW1pdHMgYmV0d2VlbiB0aGVzZSBncm91cHMuIAoKYGBge3IgY3RtYXgtc2V4LCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD03fQpjdG1heF9yZXNpZHMgJT4lIAogIGZpbHRlcihzcF9uYW1lICVpbiUgZmlsdGVyKHNleF9zYW1wbGVfc2l6ZXMsIE1hbGUgPiAwLCBGZW1hbGUgPiAwKSRTcGVjaWVzICYgCiAgICAgICAgICAgc2V4ICE9ICJqdXZlbmlsZSIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzZXgsIHkgPSByZXNpZHMsIGNvbG91ciA9IHNwX25hbWUsIGdyb3VwID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfd3JhcChzcF9uYW1lfi4sIG5jb2wgPSAyKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAzLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUsCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcihoZWlnaHQgPSAwLCB3aWR0aCA9IDAuMDUpKSArICAKICBsYWJzKHggPSAiU2V4IiwgCiAgICAgICB5ID0gIkNUbWF4IFJlc2lkdWFscyIpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICAgICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCmBgYHtyIGN0bWF4LXN0YWdlLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD02fQpjdG1heF9yZXNpZHMgJT4lIAogIGZpbHRlcihzcF9uYW1lICVpbiUgZmlsdGVyKHNleF9zYW1wbGVfc2l6ZXMsIEp1dmVuaWxlID4gMCAmIEZlbWFsZSA+IDApJFNwZWNpZXMgJiAKICAgICAgICAgICBzZXggIT0gIm1hbGUiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc2V4LCB5ID0gcmVzaWRzLCBjb2xvdXIgPSBzcF9uYW1lLCBncm91cCA9IHNwX25hbWUpKSArIAogIGZhY2V0X3dyYXAoc3BfbmFtZX4uLCBuY29sID0gMSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYsIGxpbmV3aWR0aCA9IDEpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMywKICAgICAgICAgICAgIGFscGhhID0gMC41LAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIoaGVpZ2h0ID0gMCwgd2lkdGggPSAwLjA1KSkgKyAgCiAgbGFicyh4ID0gIlNleCIsIAogICAgICAgeSA9ICJDVG1heCAowrBDKSIpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICAgICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCgpgYGB7ciB0cmFpdC12YXJpYW5jZS1jb2xsLXRlbXAsIGluY2x1ZGUgPSBGfQojIAojIEdpdmVuIHRoZSBsb25nIGdlbmVyYXRpb24gdGltZXMgb2YgdGhlc2UgY29wZXBvZHMsIGRlY3JlYXNlcyBpbiB0cmFpdCB2YXJpYW5jZSBtYXkgaW5kaWNhdGUgc2VsZWN0aW9uIG92ZXIgdGhlIHNlYXNvbmFsIGN5Y2xlLiBTaG93biBiZWxvdyBhcmUgdGhlIHZhcmlhbmNlIGluIG9ic2VydmVkIENUbWF4IGFuZCBzaXplLCBwbG90dGVkIGFnYWluc3QgY29sbGVjdGlvbiBkYXRlLiBWYXJpYW5jZSBkZWNyZWFzZXMgaW4gKlNraXN0b2RpYXB0b211cyosIGJ1dCB0aGlzIHBhdHRlcm4gaXMgZHJpdmVuIGJ5IGEgc2luZ2xlIGNvbGxlY3Rpb24gd2l0aCBoaWdoIHZhcmlhbmNlIGVhcmx5IGluIHRoZSB5ZWFyLiBTaXplIHZhcmlhbmNlIGluY3JlYXNlcyBzbGlnaHRseSBpbiAqU2tpc3RvZGlhcHRvbXVzKi4gVmFyaWFuY2UgaW4gYm90aCBDVG1heCBhbmQgc2l6ZSBpcyBmYWlybHkgY29uc3RhbnQgaW4gKkxlcHRvZGlhcHRvbXVzIG1pbnV0dXMqLCB0aGUgb25seSBvdGhlciBzcGVjaWVzIGNvbGxlY3RlZCBhY3Jvc3MgdGhlIGVudGlyZSBzZXQgb2Ygc2FtcGxlcyB0aHVzIGZhci4gCiMgCiMgZ2dwbG90KGRyb3BfbmEoYWR1bHRfc3VtbWFyaWVzLCBjdG1heF92YXIpLCBhZXMoeCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSwgeSA9IGN0bWF4X3ZhciwgY29sb3VyID0gc3BfbmFtZSkpICsgCiMgICBmYWNldF93cmFwKHNwX25hbWV+Liwgc2NhbGVzID0gImZyZWVfeSIpICsgCiMgICBnZW9tX3BvaW50KHNpemUgPSAyKSArIAojICAgZ2VvbV9zbW9vdGgoc2UgPSBGKSArIAojICAgbGFicyh4ID0gIkNvbGxlY3Rpb24gVGVtcC4gKMKwQykiLCAKIyAgICAgICAgeSA9ICJDVG1heCBWYXJpYW5jZSIpICsgCiMgICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKIyAgIHRoZW1lX21hdHRfZmFjZXRzKCkgKyAKIyAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKIyAKIyBnZ3Bsb3QoZHJvcF9uYShhZHVsdF9zdW1tYXJpZXMsIHNpemVfdmFyKSwgYWVzKHggPSBhcy5EYXRlKGNvbGxlY3Rpb25fZGF0ZSksIHkgPSBzaXplX3ZhciwgY29sb3VyID0gc3BfbmFtZSkpICsgCiMgICBmYWNldF93cmFwKHNwX25hbWV+LikgKyAKIyAgIGdlb21fcG9pbnQoc2l6ZSA9IDIpICsgCiMgICBnZW9tX3Ntb290aChzZSA9IEYpICsgCiMgICBsYWJzKHggPSAiQ29sbGVjdGlvbiBUZW1wLiAowrBDKSIsIAojICAgICAgICB5ID0gIlNpemUgVmFyaWFuY2UiKSArIAojICAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiMgICB0aGVtZV9tYXR0X2ZhY2V0cygpICsgCiMgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKCiMjIyBUcmFpdCBDb3JyZWxhdGlvbnMgYW5kIFRyYWRlLW9mZnMKCkEgcmVsYXRpb25zaGlwIGJldHdlZW4gc2l6ZSBhbmQgdXBwZXIgdGhlcm1hbCBsaW1pdHMgaGFzIGJlZW4gc3VnZ2VzdGVkIGluIGEgd2lkZSByYW5nZSBvZiBvdGhlciB0YXhhLiBTaG93biBiZWxvdyBhcmUgdGhlIG1lYXN1cmVkIHVwcGVyIHRoZXJtYWwgbGltaXRzIHBsb3R0ZWQgYWdhaW5zdCBwcm9zb21lIGxlbmd0aC4gVGhlIG92ZXJhbGwgcmVsYXRpb25zaGlwIChpbmNsdXNpdmUgb2YgYWxsIHNwZWNpZXMpIGlzIHNob3duIGFzIHRoZSBibGFjayBsaW5lIGluIHRoZSBiYWNrZ3JvdW5kLiBSZWdyZXNzaW9ucyBmb3IgZWFjaCBpbmRpdmlkdWFsIHNwZWNpZXMgYXJlIGFsc28gc2hvd24uIEZvciB0aGUgdGhyZWUgZGlhcHRvbWlkcyBhbmQgKkVwaXNjaHVyYSogdGhlcmUgaXMgYSBzbGlnaHQgbmVnYXRpdmUgcmVsYXRpb25zaGlwIGJldHdlZW4gc2l6ZSBhbmQgdGhlcm1hbCBsaW1pdHMuIEhvd2V2ZXIsIGFjcm9zcyB0aGUgZW50aXJlIGFzc2VtYmxhZ2UsIHRoZXJlIGlzIGEgc2xpZ2h0IGluY3JlYXNlIGluIHRoZXJtYWwgbGltaXRzIHdpdGggaW5jcmVhc2luZyBzaXplLiBUaGlzIG1heSwgaG93ZXZlciwgYmUgZHVlIHRvIHRoZSByZWxhdGl2ZSBvdmVycmVwcmVzZW50YXRpb24gb2YgbGFyZ2VyIHN1bW1lciBzcGVjaWVzIGxpa2UgKlNraXN0b2RpYXB0b211cyouIEluY3JlYXNpbmcgdGhlIG1lYXN1cmVtZW50cyBvbiBsYXJnZXIsIGNvbGQtd2F0ZXIgc3BlY2llcyBsaWtlICpMLiBzaWNpbGlzKiBhbmQgKkxpbW5vY2FsYW51cyogbWF5IGFsdGVyIHRoaXMgb2JzZXJ2ZWQgcGF0dGVybi4gCgpgYGB7ciBjdG1heC1zaXplLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9N30KCmZ1bGxfZGF0YSAlPiUgCiAgI2ZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAgCiAgZ2dwbG90KCBhZXMoeCA9IHNpemUsIHkgPSBjdG1heCwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZ2VvbV9zbW9vdGgoZGF0YSA9IGZ1bGxfZGF0YSwgCiAgICAgICAgICAgICAgYWVzKHggPSBzaXplLCB5ID0gY3RtYXgpLAogICAgICAgICAgICAgIG1ldGhvZCA9ICJsbSIsIAogICAgICAgICAgICAgIGNvbG91ciA9ImJsYWNrIiwgCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMi41KSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDIsIGFscGhhID0gMC44KSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwgbGluZXdpZHRoID0gMikgKyAKICBsYWJzKHggPSAiTGVuZ3RoIChtbSkiLCAKICAgICAgIHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKU2hvd24gaGVyZSBpcyB0aGUgcmVsYXRpb25zaGlwIGZvciBlYWNoIHNwZWNpZXMgaW5kaXZpZHVhbGx5LiAKCmBgYHtyIGluZC1zcC1jdG1heC1zaXplLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD02fQpmdWxsX2RhdGEgJT4lIAogICNmaWx0ZXIoc2V4ID09ICJmZW1hbGUiKSAlPiUgIAogIGdyb3VwX2J5KHNwX25hbWUpICU+JSBmaWx0ZXIobigpID4yKSAlPiUgZmlsdGVyKCFzdHJfZGV0ZWN0KHNwX25hbWUsIHBhdHRlcm4gPSAia2luZHRpIikpICU+JSAKICBnZ3Bsb3QoIGFlcyh4ID0gc2l6ZSwgeSA9IGN0bWF4LCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBmYWNldF93cmFwKHNwX25hbWV+Liwgc2NhbGVzID0gImZyZWUiLCBucm93ID0gMikgKyAKICBnZW9tX3BvaW50KHNpemUgPSAyLCBhbHBoYSA9IDAuOCkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYsIGxpbmV3aWR0aCA9IDIpICsgCiAgbGFicyh4ID0gIkxlbmd0aCAobW0pIiwgCiAgICAgICB5ID0gIkNUbWF4ICjCsEMpIiwKICAgICAgIGNvbG91ciA9ICJTcGVjaWVzIikgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKYGBge3IgbWVhbi1jdG1heC1tZWFuLXNpemUtcGxvdCwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9NX0KZnVsbF9kYXRhICU+JSAKICBncm91cF9ieShzcF9uYW1lLCBzZXgpICU+JSAKICBzdW1tYXJpemUobWVhbl9jdG1heCA9IG1lYW4oY3RtYXgsIG5hLnJtID0gVCksCiAgICAgICAgICAgIG1lYW5fc2l6ZSA9IG1lYW4oc2l6ZSwgbmEucm0gPSBUKSkgJT4lIAogICNmaWx0ZXIoc2V4ID09ICJmZW1hbGUiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gbWVhbl9zaXplLCB5ID0gbWVhbl9jdG1heCkpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGLCBsaW5ld2lkdGggPSAyLCBjb2xvdXIgPSAiYmxhY2siKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHNwX25hbWUsIHNoYXBlID0gc2V4KSwKICAgICAgICAgICAgIHNpemUgPSA1KSArIAogIGxhYnMoeCA9ICJMZW5ndGggKG1tKSIsIAogICAgICAgeSA9ICJDVG1heCAowrBDKSIsCiAgICAgICBjb2xvdXIgPSAiU3BlY2llcyIpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCgpgYGB7ciBjdG1heHJlc2lkcy1zaXplLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NywgaW5jbHVkZSA9IEZ9CmN0bWF4X3Jlc2lkcyAlPiUgCiAgI2ZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzaXplX3Jlc2lkcywgeSA9IHJlc2lkcywgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfd3JhcChzcF9uYW1lfi4pICsgCiAgZ2VvbV9wb2ludChzaXplID0gMikgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYsIGxpbmV3aWR0aCA9IDIpICsgCiAgbGFicyh4ID0gIkxlbmd0aCAobW0pIiwgCiAgICAgICB5ID0gIkNUbWF4ICjCsEMpIikgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKU2hvd24gaGVyZSBpcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gZmVjdW5kaXR5IGFuZCBzaXplLCBzaG93aW5nIHRoZSBjbGFzc2ljIHBhdHRlcm4gb2YgaW5jcmVhc2luZyBlZ2cgcHJvZHVjdGlvbiB3aXRoIGluY3JlYXNpbmcgc2l6ZS4gCgpgYGB7ciBmZWN1bmRpdHktc2l6ZSwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTd9CmN0bWF4X3Jlc2lkcyAlPiUgIAogIGRyb3BfbmEoZmVjdW5kaXR5KSAlPiUgCmdncGxvdChhZXMoeCA9IHNpemUsIHkgPSBmZWN1bmRpdHksIGNvbG91ciA9IHNwX25hbWUpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwgbGluZXdpZHRoID0gMikgKyAKICBnZW9tX3BvaW50KHNpemUgPSAyLCBhbHBoYSA9IDAuNSkgKyAKICBsYWJzKHggPSAiUHJvc29tZSBsZW5ndGggKG1tKSIsIAogICAgICAgeSA9ICJGZWN1bmRpdHkgKCMgRWdncykiLAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKSW5kaXZpZHVhbHMgbWF5IGFsc28gYWxsb2NhdGUgZW5lcmd5IHRvIGRpZmZlcmVudCBmaXRuZXNzIHJlbGF0ZWQgdHJhaXRzLCBwcmlvcml0aXppbmcgcmVwcm9kdWN0aXZlIG91dHB1dCBvdmVyIGVudmlyb25tZW50YWwgdG9sZXJhbmNlLCBmb3IgZXhhbXBsZS4gU2hvd24gYmVsb3cgaXMgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIENUbWF4IHJlc2lkdWFscyAoYWdhaW4sIGNvbnRyb2xsaW5nIGZvciB0aGUgZWZmZWN0cyBvZiBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlKSBhZ2FpbnN0IGZlY3VuZGl0eS4gV2UgY2FuIHNlZSBjbGVhcmx5IHRoYXQgaW5kaXZpZHVhbHMgd2l0aCBpbmNyZWFzZWQgZmVjdW5kaXR5IGFyZSBub3QgZGVjcmVhc2luZyB0aGVybWFsIGxpbWl0cywgc3VnZ2VzdGluZyB0aGF0IHRoZXJlIGlzIG5vIGVuZXJnZXRpYyB0cmFkZS1vZmYgYmV0d2VlbiB0aGVzZSB0cmFpdHMuIAoKYGBge3IsIGN0bWF4LWZlY3VuZGl0eSwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTd9CmN0bWF4X3Jlc2lkcyAlPiUgIAogIGRyb3BfbmEoZmVjdW5kaXR5KSAlPiUgCiAgZ2dwbG90KGFlcyh5ID0gcmVzaWRzLCB4ID0gZmVjdW5kaXR5LCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYsIGxpbmV3aWR0aCA9IDIpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMiwgYWxwaGEgPSAwLjUpICsgCiAgbGFicyh5ID0gIkNUbWF4ICjCsEMpIiwgCiAgICAgICB4ID0gIkZlY3VuZGl0eSAoIyBFZ2dzKSIpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCgpgYGB7cn0KaWYocHJlZGljdF92dWxuID09IEYpewogIGtuaXRyOjprbml0X2V4aXQoKQp9CmBgYAoKCiMjIFByZWRpY3RpbmcgVnVsbmVyYWJpbGl0eSAKVXNpbmcgdGhlIG9ic2VydmVkIHRoZXJtYWwgbGltaXQgZGF0YSwgd2UgY2FuIHByb2R1Y2UgYSBoaW5kY2FzdCBvZiB0aGVybWFsIHN0cmVzcyBmb3IgTGFrZSBDaGFtcGxhaW4gY29wZXBvZHMuIEZvciB0aGVzZSBpbml0aWFsIGFzc2F5cywgd2Ugd2lsbCBkZWZpbmUgdGhlcm1hbCBzdHJlc3MgYXMgYW55IHRpbWUgd2hlbiBtYXhpbXVtIGRhaWx5IHdhdGVyIHRlbXBlcmF0dXJlIGlzIHdpdGhpbiAywrBDIG9mIGNvcGVwb2QgQ1RtYXggb3IgaGlnaGVyLiBXZSB3aWxsIHVzZSB0aHJlZSBkaWZmZXJlbnQgc2NlbmFyaW9zOiAxKSB0aGUgYXZlcmFnZSBDVG1heCBmb3IgZWFjaCBzcGVjaWVzLCAyKSBDVG1heCBwcmVkaWN0ZWQgdXNpbmcgY29sbGVjdGlvbiB0ZW1wZXJhdHVyZXMsIGFuZCAzKSBmb3Igc3BlY2llcyB0aGF0IGhhdmUgc3VmZmljaWVudCBkYXRhLCBDVG1heCBwcmVkaWN0ZWQgdXNpbmcgd2hpY2hldmVyIGVudmlyb25tZW50YWwgZmFjdG9yIGlzIHRoZSBzdHJvbmdlc3QgY2FuZGlkYXRlIGZvciBkcml2aW5nIGFjY2xpbWF0aW9uLiBJbiBhbGwgY2FzZXMsIGRhdGEgaXMgZmlsdGVyZWQgdG8ganVzdCB0aGVybWFsIGxpbWl0cyBvZiBhZHVsdCBmZW1hbGVzLiAKCiMjIyBTY2VuYXJpbyAxCmBgYHtyfQptZWFuX2N0bWF4ID0gZnVsbF9kYXRhICU+JSAKICBmaWx0ZXIoc2V4ID09ICJmZW1hbGUiKSAlPiUgIAogIGdyb3VwX2J5KHNwX25hbWUpICU+JSAKICBzdW1tYXJpemUoIm1lYW5fY3RtYXgiID0gbWVhbihjdG1heCkpICU+JSAKICBhcnJhbmdlKG1lYW5fY3RtYXgpCgprbml0cjo6a2FibGUobWVhbl9jdG1heCkKYGBgCgpgYGB7cn0KIyAjIENvbnN0cnVjdHMgdGhlIFVSTCBmb3IgdGhlIGZ1bGwgdGVtcGVyYXR1cmUgZGF0YSBzZXQ7IFJVTiBUSElTIE9OQ0UKIyBoaW5kX3VybCA9IGNvbnN0cnVjdE5XSVNVUkwoc2l0ZU51bWJlcnMgPSBzaXRlTnVtYmVyLCBwYXJhbWV0ZXJDZCA9IHBhcmFtZXRlckNkLCBzZXJ2aWNlID0gInV2IikKIyAKIyBoaW5kX3RlbXBfZGF0YSA9IGltcG9ydFdhdGVyTUwxKGhpbmRfdXJsLCBhc0RhdGVUaW1lID0gVCkgJT4lCiMgICBtdXRhdGUoImRhdGUiID0gYXMuRGF0ZShkYXRlVGltZSkpICU+JQojICAgc2VsZWN0KGRhdGUsICJ0ZW1wIiA9IFhfMDAwMTBfMDAwMDApCiMgCiMgd3JpdGUudGFibGUoeCA9IGhpbmRfdGVtcF9kYXRhLCBmaWxlID0gImhpbmRjYXN0X3RlbXBzLmNzdiIsIHJvdy5uYW1lcyA9IEYsIHNlcCA9ICIsIikKYGBgCgpgYGB7cn0KIyBnZ3Bsb3QoaGluZF90ZW1wX2RhdGEsIGFlcyh4ID0gZGF0ZSwgeSA9IHRlbXApKSArIAojICAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDAuMSkgKyAKIyAgIGxhYnMoeCA9ICJEYXRlIiwgCiMgICAgICAgIHkgPSAiV2F0ZXIgVGVtcGVyYXR1cmUgKMKwQykiKSArCiMgICB0aGVtZV9tYXR0KCkKYGBgCgpJbiB0aGUgc2ltcGxlc3Qgc2NlbmFyaW8sIHNwZWNpZXMgdGhlcm1hbCBsaW1pdHMgYXJlIHN0YXRpYyB0aHJvdWdoIHRpbWUsIHJlcHJlc2VudGVkIGJ5IHRoZSBhdmVyYWdlIENUbWF4IG9mIGFkdWx0IGZlbWFsZSBjb3BlcG9kcy4gSW4gdGhpcyBzY2VuYXJpbywgb25seSB0aHJlZSBvZiB0aGUgc2V2ZW4gb2JzZXJ2ZWQgc3BlY2llcyBhcmUgZXhwb3NlZCB0byB0aGVybWFsIHN0cmVzcyAodGVtcGVyYXR1cmVzIHdpdGhpbiA1wrBDIG9mIENUbWF4KS4gVGVtcGVyYXR1cmVzIGFwcHJvYWNoZWQgdGhlIHRoZXJtYWwgbGltaXQgb2YgKkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMqIG9uIGEgaGFuZGZ1bCBvZiBkYXlzLiBCeSBjb250cmFzdCwgKlNlbmVjZWxsYSBjYWxhbm9pZGVzKiBhbmQgKkxpbW5vY2FsYW51cyBtYWNydXJ1cyogd2VyZSBib3RoIGV4cG9zZWQgdG8gc3Vic3RhbnRpYWwgdGhlcm1hbCBzdHJlc3MgdGhyb3VnaG91dCBhIGxhcmdlIHBvcnRpb24gb2YgdGhlIHllYXIsIGxpa2VseSBleHBsYWluaW5nIHdoeSB0aGVzZSBzcGVjaWVzIGFyZSBhYnNlbnQgZnJvbSB0aGUgY29tbXVuaXR5IGZvciB0aGUgc3VtbWVyIGFuZCBmYWxsIHBlcmlvZHMuIAoKYGBge3IgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTV9CmhpbmQxX2RhdGEgPSBoaW5kX3RlbXBfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lIAogIHN1bW1hcml6ZSgiZGFpbHlfbWF4IiA9IG1heCh0ZW1wKSwKICAgICAgICAgICAgImRhaWx5X21lYW4iID0gbWVhbih0ZW1wKSwpICU+JSAKICBiaW5kX2NvbHMocGl2b3Rfd2lkZXIobWVhbl9jdG1heCwgbmFtZXNfZnJvbSA9IHNwX25hbWUsIHZhbHVlc19mcm9tID0gbWVhbl9jdG1heCkpICU+JSAgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKC1kYXRlLCAtZGFpbHlfbWF4LCAtZGFpbHlfbWVhbiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInNwZWNpZXMiLCAKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIm1lYW5fY3RtYXgiKSAlPiUgIAogIG11dGF0ZShsaW1fZGlmZiA9IG1lYW5fY3RtYXggLSBkYWlseV9tYXgpICU+JSAgCiAgbXV0YXRlKGRveSA9IHlkYXkoZGF0ZSksCiAgICAgICAgICJtZXRob2QiID0gIk5vX2FjY2xpbWF0aW9uIikKCmhpbmRfZGFpbHlfdGVtcF9kYXRhID0gaGluZF90ZW1wX2RhdGEgJT4lCiAgdW5ncm91cCgpICU+JSAKICBncm91cF9ieShkYXRlKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fdGVtcCA9IG1lYW4odGVtcCksCiAgICAgICAgICAgIG1lZF90ZW1wID0gbWVkaWFuKHRlbXApLAogICAgICAgICAgICB2YXJfdGVtcCA9IHZhcih0ZW1wKSwgCiAgICAgICAgICAgIG1pbl90ZW1wID0gbWluKHRlbXApLCAKICAgICAgICAgICAgbWF4X3RlbXAgPSBtYXgodGVtcCkpICU+JSAKICBtdXRhdGUoInJhbmdlX3RlbXAiID0gbWF4X3RlbXAgLSBtaW5fdGVtcCkKCiN0YWJsZShoaW5kMV9kYXRhJHNwZWNpZXMpCgpoaW5kMV9kYXRhICU+JSAKICBmaWx0ZXIobGltX2RpZmYgPD0gNSkgJT4lICAKICBnZ3Bsb3QoYWVzKHggPSBkb3ksIHkgPSBsaW1fZGlmZiwgY29sb3VyID0gc3BlY2llcykpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDUsIAogICAgICAgICAgICAgY29sb3VyID0gImdyZXkiKSArIAogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsKICBnZW9tX3Ntb290aChzZSA9IEYpICsgCiAgbGFicyh4ID0gIkRheSBvZiBZZWFyIiwgCiAgICAgICB5ID0gIlByZWRpY3RlZCBXYXJtaW5nIFRvbGVyYW5jZSBcbijCsEMgQWJvdmUgRGFpbHkgTWF4KSIpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCgojIyMgU2NlbmFyaW8gMgpJbiB0aGUgc2Vjb25kIHNjZW5hcmlvLCB0aGVybWFsIGxpbWl0cyB2YXJ5IHdpdGhpbiBhbmQgYmV0d2VlbiBzcGVjaWVzLiBBIHNpbXBsZSBtb2RlbCBpcyB1c2VkIHRvIHByZWRpY3Qgc3BlY2llcyB0aGVybWFsIGxpbWl0cyBiYXNlZCBvbiBtZWFuIGRhaWx5IHRlbXBlcmF0dXJlIChDVG1heCBhcyBhIGZ1bmN0aW9uIG9mIHNwZWNpZXMgYW5kIGNvbGxlY3Rpb24gdGVtcGVyYXR1cmUsIGJ1dCB3aXRob3V0IHRoZSBpbnRlcmFjdGlvbiBiZXR3ZWVuIHRoZXNlIHR3byBmYWN0b3JzKS4gVGhlc2UgcHJlZGljdGVkIHRoZXJtYWwgbGltaXRzIGFyZSB0aGVuIGNvbXBhcmVkIGFnYWluc3QgdGhlIG1heGltdW0gZGFpbHkgdGVtcGVyYXR1cmUgdG8gZXN0aW1hdGUgdGhlcm1hbCBzdHJlc3MsIGFzIGluIFNjZW5hcmlvIDEuIEluY2x1ZGluZyB0aGlzIHNpbXBsZSBmb3JtIG9mIGFjY2xpbWF0aW9uIGluIHRoZSBtb2RlbCByZWR1Y2VkIHRoZSBkZWdyZWUgb2YgdGhlcm1hbCBzdHJlc3MgZm9yIGVhY2ggc3BlY2llcywgZWxpbWluYXRpbmcgaXQgZW50aXJlbHkgZm9yICpMZXB0b2RpYXB0b211cyBzaWNpbGlzKi4gTm90ZSB0aGF0IHRoZSBtYWduaXR1ZGUgb2YgdGhlIHByZWRpY3RlZCBzdHJlc3MgaXMgIGxvdyBlbm91Z2ggdGhhdCByZW1vdmluZyB0aGUgNcKwQyBidWZmZXIgYXJvdW5kIHRoZSBwcmVkaWN0ZWQgdGhlcm1hbCBsaW1pdHMgd291bGQgYWN0dWFsbHkgbGltaXQgcHJlZGljdGVkIHRoZXJtYWwgc3RyZXNzIHRvIGp1c3QgYSBmZXcgZGF5cyBmb3IgKlNlbmVjZWxsYSBjYWxhbm9pZGVzKi4gCgpgYGB7ciBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0xMH0KaGluZGNhc3RfbW9kZWwxID0gbG0oZGF0YSA9IGZpbHRlcihmdWxsX2RhdGEsIHNleCA9PSAiZmVtYWxlIiksCiAgICAgICAgICAgICAgICAgICAgIGN0bWF4IH4gY29sbGVjdGlvbl90ZW1wICsgc3BfbmFtZSkKCmhpbmQyX2RhdGEgPSBoaW5kX3RlbXBfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lIAogIHN1bW1hcml6ZSgiY29sbGVjdGlvbl90ZW1wIiA9IG1lYW4odGVtcCksCiAgICAgICAgICAgICJkYWlseV9tYXgiID0gbWF4KHRlbXApKSAlPiUgCiAgYmluZF9jb2xzKAogICAgcGl2b3Rfd2lkZXIobWVhbl9jdG1heCwgCiAgICAgICAgICAgICAgICBuYW1lc19mcm9tID0gc3BfbmFtZSwgCiAgICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IG1lYW5fY3RtYXgpKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKC1kYXRlLCAtZGFpbHlfbWF4LCAtY29sbGVjdGlvbl90ZW1wKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAic3BfbmFtZSIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAibWVhbl9jdG1heCIpICU+JSAKICBzZWxlY3QoLW1lYW5fY3RtYXgpICU+JSAKICBtdXRhdGUoInByZWRfY3RtYXgiID0gcHJlZGljdC5sbSAoaGluZGNhc3RfbW9kZWwxLCBuZXdkYXRhID0gLikpICU+JSAKICBzZWxlY3QoZGF0ZSwgImRhaWx5X21lYW4iID0gY29sbGVjdGlvbl90ZW1wLCBkYWlseV9tYXgsICJzcGVjaWVzIiA9IHNwX25hbWUsIHByZWRfY3RtYXgpICU+JSAKICBtdXRhdGUobGltX2RpZmYgPSBwcmVkX2N0bWF4IC0gZGFpbHlfbWF4KSAlPiUgCiAgI2ZpbHRlcihsaW1fZGlmZiA8PSAwKSAlPiUgIAogIG11dGF0ZShkb3kgPSB5ZGF5KGRhdGUpLAogICAgICAgICAibWV0aG9kIiA9ICJDb25zdGFudF9hY2NsaW1hdGlvbiIpCgojIGdncGxvdChoaW5kMl9kYXRhLCBhZXMoeCA9IGRhaWx5X21lYW4sIHkgPSBwcmVkX2N0bWF4LCBjb2xvdXIgPSBzcGVjaWVzKSkgKwojICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgCgojIHRhYmxlKGhpbmQyX2RhdGEkc3BlY2llcykKaGluZDJfZGF0YSAlPiUgIAogIGZpbHRlcihsaW1fZGlmZiA8PSA1KSAlPiUgIAogIGdncGxvdChhZXMoeCA9IGRveSwgeSA9IGxpbV9kaWZmLCBjb2xvdXIgPSBzcGVjaWVzKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNSwgCiAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleSIpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKwogIGdlb21fc21vb3RoKCkgKyAKICBsYWJzKHggPSAiRGF5IG9mIFllYXIiLCAKICAgICAgIHkgPSAiUHJlZGljdGVkIFdhcm1pbmcgVG9sZXJhbmNlIFxuKMKwQyBBYm92ZSBEYWlseSBNYXgpIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpgYGAKCiMjIyBTY2VuYXJpbyAzClRoZSBmaW5hbCBzY2VuYXJpbyBhbGxvd3MgdGhlIGVudmlyb25tZW50YWwgdmFyaWFibGUgdXNlZCB0byBwcmVkaWN0IENUbWF4IHRvIHZhcnkgYmV0d2VlbiBzcGVjaWVzLiBGb3Igc3BlY2llcyBvYnNlcnZlZCBpbiBmZXdlciB0aGFuIDUgY29sbGVjdGlvbnMsIHdlIHVzZSB0aGUgc2FtZSBhcHByb2FjaCBhcyBpbiBTY2VuYXJpbyAyLiBGb3Igc3BlY2llcyBvYnNlcnZlZCBpbiBtb3JlIHRoYW4gNSBjb2xsZWN0aW9ucywgaG93ZXZlciwgdGhlIGZhY3RvciB3aXRoIHRoZSBzdHJvbmdlc3QgY29ycmVsYXRpb24gd2l0aCBDVG1heCBpcyB1c2VkIHRvIHByZWRpY3QgdGhlcm1hbCBsaW1pdHMuIFRoZXNlIGZhY3RvcnMgYXJlIGluY2x1ZGVkIGJlbG93LgoKYGBge3J9CmhpbmRfcHJlZHMgPSBjb3JyX3ZhbHMgJT4lICAKICBmaWx0ZXIoc2lnID09ICJTaWcuIikgJT4lIAogIGRyb3BfbmEoY29ycmVsYXRpb24pICU+JSAKICBncm91cF9ieShzcF9uYW1lKSAlPiUKICBhcnJhbmdlKGRlc2MoY29ycmVsYXRpb24pKSAlPiUgCiAgc2xpY2VfaGVhZChuID0gMSkgJT4lIAogIHNlbGVjdCgiU3BlY2llcyIgPSBzcF9uYW1lLCAiUHJlZGljdG9yIiA9IHBhcmFtZXRlciwgIkR1cmF0aW9uIiA9IGR1cmF0aW9uLCAiQ29ycmVsYXRpb24iID0gY29ycmVsYXRpb24sICJQLVZhbHVlIiA9IHAudmFsdWUpCgprbml0cjo6a2FibGUoaGluZF9wcmVkcywgYWxpZ24gPSAiYyIpCmBgYAoKYGBge3J9CmhpbmQzX2RhdGEgPSBoaW5kMl9kYXRhICU+JSAjIENvbnRhaW5zIGRhdGEgZm9yIHNwZWNpZXMgdGhhdCB3b24ndCBjaGFuZ2UgZnJvbSBzY2VuYXJpbyAyCiAgZmlsdGVyKCEoc3BlY2llcyAlaW4lIGNvcnJfdmFscyRzcF9uYW1lKSkKCnByZWRzX3RvX3B1bGwgPSBoaW5kX3ByZWRzICU+JSAgCiAgc2VsZWN0KFNwZWNpZXMsIFByZWRpY3RvciwgRHVyYXRpb24pIAoKZm9yKGkgaW4gMTpsZW5ndGgocHJlZHNfdG9fcHVsbCRTcGVjaWVzKSl7CiAgCiAgaWYocHJlZHNfdG9fcHVsbCREdXJhdGlvbltpXSA9PSAicHJpb3IiKXsgI1RoZSBwcmlvciBkYXkgdGVtcGVyYXR1cmUgbWV0cmljcyBzaG91bGQgYmUgdXNlZAogICAgZHVyYXRpb24gPSBOQQogICAgCiAgICBwcmVkaWN0b3JzID0gaGluZF9kYWlseV90ZW1wX2RhdGEgJT4lIAogICAgICBtdXRhdGUoZGF0ZSA9IGRhdGUgKyAxKSAKICAgIAogICAgcGFyYW1ldGVyID0gcHJlZHNfdG9fcHVsbCRQcmVkaWN0b3JbaV0KICAgIAogICAgbW9kZWxfZGF0YSA9IGZ1bGxfZGF0YSAlPiUKICAgICAgZmlsdGVyKHNwX25hbWUgJWluJSBwcmVkc190b19wdWxsJFNwZWNpZXNbaV0pICU+JSAKICAgICAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAogICAgICBtdXRhdGUoY29sbGVjdGlvbl9kYXRlID0gYXNfZGF0ZShjb2xsZWN0aW9uX2RhdGUpKSAlPiUgCiAgICAgIGlubmVyX2pvaW4ocHJlZGljdG9ycywgam9pbl9ieShjb2xsZWN0aW9uX2RhdGUgPT0gZGF0ZSkpICU+JSAgCiAgICAgIHNlbGVjdChjdG1heCwgY29udGFpbnMocGFyYW1ldGVyKSkKICAgIAogICAgaWYoZGltKG1vZGVsX2RhdGEpWzJdID09IDIpewogICAgICBoaW5kLm1vZGVsID0gbG0oZGF0YSA9IG1vZGVsX2RhdGEsIAogICAgICAgICAgICAgICAgICAgICAgY3RtYXggfiAuKQogICAgICAKICAgICAgc3BfZGF0YSA9IHByZWRpY3RvcnMgJT4lIAogICAgICAgIHNlbGVjdChkYXRlLCBjb250YWlucyhwYXJhbWV0ZXIpKSAlPiUgCiAgICAgICAgbXV0YXRlKHByZWRfY3RtYXggPSBwcmVkaWN0KGhpbmQubW9kZWwsIG5ld2RhdGEgPSAuKSkgJT4lICAKICAgICAgICBzZWxlY3QoZGF0ZSwgcHJlZF9jdG1heCkgJT4lIAogICAgICAgIGlubmVyX2pvaW4oaGluZF9kYWlseV90ZW1wX2RhdGEsIGJ5ID0gYygiZGF0ZSIpKSAlPiUgCiAgICAgICAgbXV0YXRlKCJzcGVjaWVzIiA9IHByZWRzX3RvX3B1bGwkU3BlY2llc1tpXSwKICAgICAgICAgICAgICAgImRveSIgPSB5ZGF5KGRhdGUpLAogICAgICAgICAgICAgICBsaW1fZGlmZiA9IHByZWRfY3RtYXggLSBtYXhfdGVtcCkgJT4lIAogICAgICAgIHNlbGVjdChkYXRlLCBkYWlseV9tZWFuID0gbWVhbl90ZW1wLCBkYWlseV9tYXggPSBtYXhfdGVtcCwgc3BlY2llcywgcHJlZF9jdG1heCwgbGltX2RpZmYsIGRveSkKICAgICAgCiAgICAgIGhpbmQzX2RhdGEgPSBiaW5kX3Jvd3MoaGluZDNfZGF0YSwgc3BfZGF0YSkKICAgIH1lbHNlewogICAgICBwcmludCgiVG9vIG1hbnkgY29sdW1ucyBzZWxlY3RlZCIpCiAgICB9CiAgICAKICAgIAogIH1lbHNlewogICAgZHVyYXRpb24gPSBhcy5udW1lcmljKHByZWRzX3RvX3B1bGwkRHVyYXRpb25baV0pCiAgfQogIAogIGlmKHByZWRzX3RvX3B1bGwkRHVyYXRpb25baV0gIT0gInByaW9yIiAmIGlzLm5hKGR1cmF0aW9uKSl7ICNEYWlseSB0ZW1wZXJhdHVyZXMgc2hvdWxkIGJlIHVzZWQsIGFzIGluIFNjZW5hcmlvIDIKICAgIHNwX2RhdGEgPSBoaW5kMl9kYXRhICU+JSAKICAgICAgZmlsdGVyKHNwZWNpZXMgPT0gcHJlZHNfdG9fcHVsbCRTcGVjaWVzW2ldKQogICAgCiAgICBoaW5kM19kYXRhID0gYmluZF9yb3dzKGhpbmQzX2RhdGEsIHNwX2RhdGEpCiAgfQogIAogIGlmKGlzLm51bWVyaWMoZHVyYXRpb24pKXsKICAgICNOZWl0aGVyIHRoZSBwcmlvciBkYXkgbm9yIGRheSBvZiBtZXRyaWNzIHNob3VsZCBiZSB1c2VkOyB1c2UgZHVyYXRpb24gYXMgbl9kYXlzCiAgICAKICAgIHByZWRpY3RvcnMgPSBnZXRfcHJlZGljdG9ycyhkYWlseV92YWx1ZXMgPSBoaW5kX2RhaWx5X3RlbXBfZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X3RlbXAgPSBoaW5kX3RlbXBfZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbl9kYXlzID0gZHVyYXRpb24pCiAgICAKICAgIHBhcmFtZXRlciA9IHByZWRzX3RvX3B1bGwkUHJlZGljdG9yW2ldCiAgICAKICAgIG1vZGVsX2RhdGEgPSBmdWxsX2RhdGEgJT4lCiAgICAgIGZpbHRlcihzcF9uYW1lICVpbiUgcHJlZHNfdG9fcHVsbCRTcGVjaWVzW2ldKSAlPiUgCiAgICAgIGZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICAgICAgbXV0YXRlKGNvbGxlY3Rpb25fZGF0ZSA9IGFzX2RhdGUoY29sbGVjdGlvbl9kYXRlKSkgJT4lIAogICAgICBpbm5lcl9qb2luKHByZWRpY3RvcnMsIGpvaW5fYnkoY29sbGVjdGlvbl9kYXRlID09IGRhdGUpKSAlPiUgIAogICAgICBzZWxlY3QoY3RtYXgsIGNvbnRhaW5zKHBhc3RlKCJkYXlfIiwgcGFyYW1ldGVyLCBzZXAgPSAiIikpKQogICAgCiAgICBpZihkaW0obW9kZWxfZGF0YSlbMl0gPT0gMil7CiAgICAgIGhpbmQubW9kZWwgPSBsbShkYXRhID0gbW9kZWxfZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICBjdG1heCB+IC4pCiAgICAgIAogICAgICBzcF9kYXRhID0gcHJlZGljdG9ycyAlPiUgCiAgICAgICAgc2VsZWN0KGRhdGUsIGNvbnRhaW5zKHBhcmFtZXRlcikpICU+JSAKICAgICAgICBtdXRhdGUocHJlZF9jdG1heCA9IHByZWRpY3QoaGluZC5tb2RlbCwgbmV3ZGF0YSA9IC4pKSAlPiUgIAogICAgICAgIHNlbGVjdChkYXRlLCBwcmVkX2N0bWF4KSAlPiUgCiAgICAgICAgaW5uZXJfam9pbihoaW5kX2RhaWx5X3RlbXBfZGF0YSwgYnkgPSBjKCJkYXRlIikpICU+JSAKICAgICAgICBtdXRhdGUoInNwZWNpZXMiID0gcHJlZHNfdG9fcHVsbCRTcGVjaWVzW2ldLAogICAgICAgICAgICAgICAiZG95IiA9IHlkYXkoZGF0ZSksCiAgICAgICAgICAgICAgIGxpbV9kaWZmID0gcHJlZF9jdG1heCAtIG1heF90ZW1wKSAlPiUgCiAgICAgICAgc2VsZWN0KGRhdGUsIGRhaWx5X21lYW4gPSBtZWFuX3RlbXAsIGRhaWx5X21heCA9IG1heF90ZW1wLCBzcGVjaWVzLCBwcmVkX2N0bWF4LCBsaW1fZGlmZiwgZG95KQogICAgICAKICAgICAgaGluZDNfZGF0YSA9IGJpbmRfcm93cyhoaW5kM19kYXRhLCBzcF9kYXRhKQogICAgICAKICAgIH1lbHNlewogICAgICBwcmludCgiVG9vIG1hbnkgY29sdW1ucyBzZWxlY3RlZCIpCiAgICB9CiAgICAKICB9Cn0KCmhpbmQzX2RhdGEgPSBoaW5kM19kYXRhICU+JSAKICBtdXRhdGUoIm1ldGhvZCIgPSAiVmFyaWFibGVfYWNjbGltYXRpb24iKQpgYGAKClRoaXMgdGhpcmQgYXBwcm9hY2ggZGlkIG5vdCBhZmZlY3QgdGhlIHByZWRpY3RlZCBwYXR0ZXJucyBpbiAqTGltbm9jYWxhbnVzKiBvciAqU2VuZWNlbGxhKiAobmVpdGhlciBzcGVjaWVzIGhhcyBiZWVuIG9ic2VydmVkIGluIGVub3VnaCBjb2xsZWN0aW9ucyB0byBlc3RpbWF0ZSB0aGUgZWZmZWN0cyBvZiBkaWZmZXJlbnQgZW52aXJvbm1lbnRhbCBmYWN0b3JzKS4gQ2hhbmdpbmcgdGhlIGFjY2xpbWF0aW9uIGFwcHJvYWNoIGRpZCBhZmZlY3QgcGF0dGVybnMgaW4gdGhlcm1hbCBsaW1pdHMgaW4gdGhlIG90aGVyIHNwZWNpZXMgdGhvdWdoLiBUaGUgZmlndXJlIGJlbG93IHNob3dzIGhvdyBwcmVkaWN0ZWQgd2FybWluZyB0b2xlcmFuY2UgdmFyaWVzIG92ZXIgdGhlIHllYXIgaW4gdGhlIHNldmVuIHNwZWNpZXMsIGJhc2VkIG9uIHRoZSB0aHJlZSBkaWZmZXJlbnQgcHJlZGljdGlvbiBtZXRob2RzLiBJbiBnZW5lcmFsLCBjb25zdGFudCB0aGVybWFsIGxpbWl0cyAodGhlICdubyBhY2NsaW1hdGlvbicgbWV0aG9kKSByZXN1bHRlZCBpbiBsYXJnZXIgd2FybWluZyB0b2xlcmFuY2UgZHVyaW5nIHRoZSB3aW50ZXIgYW5kIGxvd2VyIHdhcm1pbmcgdG9sZXJhbmNlIGR1cmluZyB0aGUgc3VtbWVyLCBhbHRob3VnaCB0aGlzIGVmZmVjdCB3YXMgc21hbGwgaW4gbW9zdCBzcGVjaWVzLiAgICAgCgpgYGB7ciBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9MTB9CnN5bnRoZXNpcyA9IGJpbmRfcm93cygKICBzZWxlY3QoaGluZDFfZGF0YSwgZGF0ZSwgZG95LCBkYWlseV9tZWFuLCBkYWlseV9tYXgsIHNwZWNpZXMsICJwcmVkX2N0bWF4IiA9IG1lYW5fY3RtYXgsIGxpbV9kaWZmLCBtZXRob2QpLAogIHNlbGVjdChoaW5kMl9kYXRhLCBkYXRlLCBkb3ksIGRhaWx5X21lYW4sIGRhaWx5X21heCwgIHNwZWNpZXMsIHByZWRfY3RtYXgsIGxpbV9kaWZmLCBtZXRob2QpLAogIHNlbGVjdChoaW5kM19kYXRhLCBkYXRlLCBkb3ksIGRhaWx5X21lYW4sIGRhaWx5X21heCwgIHNwZWNpZXMsIHByZWRfY3RtYXgsIGxpbV9kaWZmLCBtZXRob2QpKSAlPiUgCiAgbXV0YXRlKG1ldGhvZCA9IGZjdF9yZWxldmVsKG1ldGhvZCwgIk5vX2FjY2xpbWF0aW9uIiwgIkNvbnN0YW50X2FjY2xpbWF0aW9uIiwgIlZhcmlhYmxlX2FjY2xpbWF0aW9uIikpCgpjbGltYXRvbG9neSA9IHN5bnRoZXNpcyAlPiUgCiAgZ3JvdXBfYnkoc3BlY2llcywgZG95LCBtZXRob2QpICU+JSAgCiAgc3VtbWFyaXNlKCJtZWFuX2RpZmYiID0gbWVhbihsaW1fZGlmZiksCiAgICAgICAgICAgICJtaW5fZGlmZiIgPSBtaW4obGltX2RpZmYpLAogICAgICAgICAgICAibWF4X2RpZmYiID0gbWF4KGxpbV9kaWZmKSkgJT4lIAogIG11dGF0ZShtZXRob2QgPSBmY3RfcmVsZXZlbChtZXRob2QsICJOb19hY2NsaW1hdGlvbiIsICJDb25zdGFudF9hY2NsaW1hdGlvbiIsICJWYXJpYWJsZV9hY2NsaW1hdGlvbiIpKQoKYWNjX2VmZmVjdHMgPSBzeW50aGVzaXMgJT4lIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKGRhdGUsIHNwZWNpZXMsIGRveSksIAogICAgICAgICAgICAgIG5hbWVzX2Zyb20gPSBtZXRob2QsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gbGltX2RpZmYpICU+JSAgCiAgbXV0YXRlKCJjb25zdF9hY2NfZWZmZWN0IiA9IENvbnN0YW50X2FjY2xpbWF0aW9uIC0gTm9fYWNjbGltYXRpb24sCiAgICAgICAgICJ2YXJfYWNjX2VmZmVjdCIgPSBWYXJpYWJsZV9hY2NsaW1hdGlvbiAtIE5vX2FjY2xpbWF0aW9uKQoKZ2dwbG90KHN5bnRoZXNpcywgYWVzKHggPSBkb3ksIHkgPSBsaW1fZGlmZiwgY29sb3VyID0gbWV0aG9kKSkgKyAKICBmYWNldF93cmFwKHNwZWNpZXN+LikgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDUsIGNvbG91ciA9ICJncmV5IikgKyAKICBnZW9tX3BvaW50KGFscGhhID0gMC4xKSArIAogIGxhYnMoeCA9ICJEYXkgb2YgWWVhciIsIAogICAgICAgeSA9ICJQcmVkaWN0ZWQgV2FybWluZyBUb2xlcmFuY2UgKMKwQyBBYm92ZSBEYWlseSBNYXgpIikgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cyhiYXNlX3NpemUgPSAxOCkgKyAKICB0aGVtZShzdHJpcC50ZXh0LngudG9wID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpCmBgYAoKYGBge3IsIGluY2x1ZGUgPSBGfQp5ZWFybHlfc3VtbWFyeSA9IHN5bnRoZXNpcyAlPiUgIAogIG11dGF0ZSgieWVhciIgPSB5ZWFyKGRhdGUpKSAlPiUgCiAgZ3JvdXBfYnkoc3BlY2llcywgeWVhciwgbWV0aG9kKSAlPiUgCiAgICBzdW1tYXJpc2UoIm1pbl93dCIgPSBtaW4obGltX2RpZmYpLAogICAgICAgICAgICAgICJtYXhfd3QiID0gbWF4KGxpbV9kaWZmKSkgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gYyhtaW5fd3QsIG1heF93dCksIAogICAgICAgICAgICAgICBuYW1lc190byA9ICJtZXRyaWMiLCAKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInd0IikKCmdncGxvdCh5ZWFybHlfc3VtbWFyeSwgYWVzKHggPSBtZXRob2QsIHkgPSB3dCwgY29sb3VyID0gbWV0cmljKSkgKyAKICBmYWNldF93cmFwKC5+c3BlY2llcykgKyAKICBnZW9tX3BvaW50KCkgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMDAsIGhqdXN0ID0gMCwgdmp1c3QgPSAwLjUpKQpgYGAKCg==